From f78f0b5f796fb52781084a1136a11cb091d21704 Mon Sep 17 00:00:00 2001 From: Tate Date: Wed, 24 Apr 2024 08:18:15 -0600 Subject: [PATCH 01/34] Remove usages of docker container names for urls (#12929) We change names on retries but do not update the container names in the requestor so it was not a stable way to get the urls. We already have other stable ways to get the urls so just use those. --- integration-tests/docker/test_env/cl_node.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go index 7eee9231b17..8bb83cc8ee4 100644 --- a/integration-tests/docker/test_env/cl_node.go +++ b/integration-tests/docker/test_env/cl_node.go @@ -308,7 +308,7 @@ func (n *ClNode) containerStartOrRestart(restartDb bool) error { // If the node secrets TOML is not set, generate it with the default template nodeSecretsToml, err := templates.NodeSecretsTemplate{ PgDbName: n.PostgresDb.DbName, - PgHost: n.PostgresDb.ContainerName, + PgHost: strings.Split(n.PostgresDb.InternalURL.Host, ":")[0], PgPort: n.PostgresDb.InternalPort, PgPassword: n.PostgresDb.Password, CustomSecrets: n.NodeSecretsConfigTOML, @@ -339,14 +339,6 @@ func (n *ClNode) containerStartOrRestart(restartDb bool) error { return fmt.Errorf("%s err: %w", ErrStartCLNodeContainer, err) } - // retries can change the container name which affects urls used later - // so update to use the name that actually started - n.ContainerName, err = container.Name(context.Background()) - if err != nil { - return err - } - n.ContainerName = strings.Replace(n.ContainerName, "/", "", -1) - clEndpoint, err := test_env.GetEndpoint(testcontext.Get(n.t), container, "http") if err != nil { return err @@ -374,7 +366,7 @@ func (n *ClNode) containerStartOrRestart(restartDb bool) error { if err != nil { return fmt.Errorf("%s err: %w", ErrConnectNodeClient, err) } - clClient.Config.InternalIP = n.ContainerName + n.Container = container n.API = clClient From 0f28e363920a5d07587ed3b3db028ef232b88b6b Mon Sep 17 00:00:00 2001 From: Radek Scheibinger Date: Wed, 24 Apr 2024 16:34:47 +0200 Subject: [PATCH 02/34] Validate if all required env vars are supplied. (#12879) * Decouple crib config from cl-cluster helm chart * Validate required env vars Validate if all required env vars are supplied * explain how to fix missing vars * add info about example --- crib/devspace.yaml | 2 ++ crib/scripts/check_env_vars.sh | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100755 crib/scripts/check_env_vars.sh diff --git a/crib/devspace.yaml b/crib/devspace.yaml index cc82c6a464c..9c2895e9ac6 100644 --- a/crib/devspace.yaml +++ b/crib/devspace.yaml @@ -73,6 +73,8 @@ images: MACOS_SDK_DIR=$(pwd)/tools/bin/MacOSX12.3.sdk IMAGE=$image ./tools/bin/goreleaser_wrapper release --snapshot --clean --config .goreleaser.devspace.yaml docker push $image hooks: + - command: ./scripts/check_env_vars.sh + events: [ "before:deploy:app" ] - wait: running: true terminatedWithCode: 0 diff --git a/crib/scripts/check_env_vars.sh b/crib/scripts/check_env_vars.sh new file mode 100755 index 00000000000..f26f78e7470 --- /dev/null +++ b/crib/scripts/check_env_vars.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# List of required environment variables +required_vars=( + "DEVSPACE_IMAGE" + "DEVSPACE_INGRESS_CIDRS" + "DEVSPACE_INGRESS_BASE_DOMAIN" + "DEVSPACE_INGRESS_CERT_ARN" + "DEVSPACE_K8S_POD_WAIT_TIMEOUT" + "NS_TTL" + ) + +missing_vars=0 # Counter for missing variables + +# Check each variable +for var in "${required_vars[@]}"; do + if [ -z "${!var}" ]; then # If variable is unset or empty + echo "Error: Environment variable $var is not set." + missing_vars=$((missing_vars + 1)) + fi +done + +# Exit with an error if any variables were missing +if [ $missing_vars -ne 0 ]; then + echo "Total missing environment variables: $missing_vars" + echo "To fix it, add missing variables in the \"crib/.env\" file." + echo "you can find example of the .env config in the \"crib/.env.example\"" + exit 1 +else + echo "All required environment variables are set." +fi \ No newline at end of file From 5276e02da9245b2b43f49cde89295d0757b5a07c Mon Sep 17 00:00:00 2001 From: Cedric Date: Wed, 24 Apr 2024 15:44:53 +0100 Subject: [PATCH 03/34] [chore] Bump chainlink-common/pkg/capabilities (#12946) --- core/capabilities/registry_test.go | 6 ++++++ core/capabilities/targets/write_target.go | 1 + core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 ++-- core/services/workflows/engine_test.go | 6 ++++++ go.mod | 2 +- go.sum | 4 ++-- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 ++-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 ++-- 11 files changed, 25 insertions(+), 12 deletions(-) diff --git a/core/capabilities/registry_test.go b/core/capabilities/registry_test.go index 3bed31a957a..ccff0a5360e 100644 --- a/core/capabilities/registry_test.go +++ b/core/capabilities/registry_test.go @@ -42,6 +42,7 @@ func TestRegistry(t *testing.T) { capabilities.CapabilityTypeAction, "capability-1-description", "v1.0.0", + nil, ) require.NoError(t, err) @@ -70,6 +71,7 @@ func TestRegistry_NoDuplicateIDs(t *testing.T) { capabilities.CapabilityTypeAction, "capability-1-description", "v1.0.0", + nil, ) require.NoError(t, err) @@ -82,6 +84,7 @@ func TestRegistry_NoDuplicateIDs(t *testing.T) { capabilities.CapabilityTypeConsensus, "capability-2-description", "v1.0.0", + nil, ) require.NoError(t, err) c2 := &mockCapability{CapabilityInfo: ci} @@ -106,6 +109,7 @@ func TestRegistry_ChecksExecutionAPIByType(t *testing.T) { capabilities.CapabilityTypeAction, "capability-1-description", "v1.0.0", + nil, ) require.NoError(t, err) @@ -126,6 +130,7 @@ func TestRegistry_ChecksExecutionAPIByType(t *testing.T) { capabilities.CapabilityTypeTarget, "capability-1-description", "v1.0.0", + nil, ) require.NoError(t, err) @@ -159,6 +164,7 @@ func TestRegistry_ChecksExecutionAPIByType(t *testing.T) { capabilities.CapabilityTypeConsensus, "capability-1-description", "v1.0.0", + nil, ) require.NoError(t, err) diff --git a/core/capabilities/targets/write_target.go b/core/capabilities/targets/write_target.go index 47f1048211e..3349e05003e 100644 --- a/core/capabilities/targets/write_target.go +++ b/core/capabilities/targets/write_target.go @@ -63,6 +63,7 @@ func NewEvmWrite(chain legacyevm.Chain, lggr logger.Logger) *EvmWrite { capabilities.CapabilityTypeTarget, "Write target.", "v1.0.0", + nil, ) return &EvmWrite{ diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 5be5d137696..9788679dd98 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -21,7 +21,7 @@ require ( github.com/prometheus/client_golang v1.17.0 github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c diff --git a/core/scripts/go.sum b/core/scripts/go.sum index b26bad1299e..45ef18e49ca 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1185,8 +1185,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9 h1:elDIBChe7ByPNvCyrSjMLTPKrgY+sKgzzlWe2p3wokY= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 h1:54hM3/SrOM166it2K35hGb5K7gQ49/Op0aHp9WkqpqU= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 h1:MvaNzuaQh1vX4CAYLM8qFd99cf0ZF1JNwtDZtLU7WvU= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index 7bb6cd00c1c..448ff13ec79 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -136,6 +136,7 @@ func TestEngineWithHardcodedWorkflow(t *testing.T) { capabilities.CapabilityTypeTarget, "a write capability targeting ethereum sepolia testnet", "v1.0.0", + nil, ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { m := req.Inputs.Underlying["report"].(*values.Map) @@ -219,6 +220,7 @@ func mockTrigger(t *testing.T) (capabilities.TriggerCapability, capabilities.Cap capabilities.CapabilityTypeTrigger, "issues a trigger when a mercury report is received.", "v1.0.0", + nil, ), ch: make(chan capabilities.CapabilityResponse, 10), } @@ -242,6 +244,7 @@ func mockFailingConsensus() *mockCapability { capabilities.CapabilityTypeConsensus, "an ocr3 consensus capability", "v3.0.0", + nil, ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { return capabilities.CapabilityResponse{}, errors.New("fatal consensus error") @@ -256,6 +259,7 @@ func mockConsensus() *mockCapability { capabilities.CapabilityTypeConsensus, "an ocr3 consensus capability", "v3.0.0", + nil, ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { obs := req.Inputs.Underlying["observations"] @@ -282,6 +286,7 @@ func mockTarget() *mockCapability { capabilities.CapabilityTypeTarget, "a write capability targeting polygon mumbai testnet", "v1.0.0", + nil, ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { m := req.Inputs.Underlying["report"].(*values.Map) @@ -383,6 +388,7 @@ func mockAction() (*mockCapability, values.Value) { capabilities.CapabilityTypeAction, "a read chain action", "v1.0.0", + nil, ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { diff --git a/go.mod b/go.mod index 752dd110c49..b357e57eac5 100644 --- a/go.mod +++ b/go.mod @@ -72,7 +72,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chain-selectors v1.0.10 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab diff --git a/go.sum b/go.sum index 5f042f2e4c4..664ddd5efe0 100644 --- a/go.sum +++ b/go.sum @@ -1180,8 +1180,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9 h1:elDIBChe7ByPNvCyrSjMLTPKrgY+sKgzzlWe2p3wokY= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 h1:54hM3/SrOM166it2K35hGb5K7gQ49/Op0aHp9WkqpqU= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 h1:MvaNzuaQh1vX4CAYLM8qFd99cf0ZF1JNwtDZtLU7WvU= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 327e5e69d94..d07e68c9f7a 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -25,7 +25,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 github.com/smartcontractkit/chainlink-testing-framework v1.28.4 github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 577ae3f2a0d..efef8224d85 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1517,8 +1517,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9 h1:elDIBChe7ByPNvCyrSjMLTPKrgY+sKgzzlWe2p3wokY= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 h1:54hM3/SrOM166it2K35hGb5K7gQ49/Op0aHp9WkqpqU= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 h1:MvaNzuaQh1vX4CAYLM8qFd99cf0ZF1JNwtDZtLU7WvU= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index eaf0332af63..a7a37ab1e0e 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -16,7 +16,7 @@ require ( github.com/rs/zerolog v1.30.0 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 github.com/smartcontractkit/chainlink-testing-framework v1.28.4 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 631336409b3..d50656bfed5 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1500,8 +1500,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9 h1:elDIBChe7ByPNvCyrSjMLTPKrgY+sKgzzlWe2p3wokY= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419205832-845fa69af8d9/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 h1:54hM3/SrOM166it2K35hGb5K7gQ49/Op0aHp9WkqpqU= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 h1:MvaNzuaQh1vX4CAYLM8qFd99cf0ZF1JNwtDZtLU7WvU= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= From 0f23216f5d4da07084255f79a808ba591c9b860d Mon Sep 17 00:00:00 2001 From: Ilja Pavlovs Date: Wed, 24 Apr 2024 19:13:51 +0300 Subject: [PATCH 04/34] VRF-824: add reorg test for VRF v2 and v2 Plus (#12939) * VRF-824: add reorg test for VRF v2 Plus * VRF-824: fixing lint * VRF-824: cleaning up * VRF-824: fixing test * VRF-824: fixing test * VRF-824: fixing test * VRF-824: adding vrfv2 test for reorg * VRF-824: fixing lint * VRF-824: migrating to resty for raw rpc call --- .github/workflows/integration-tests.yml | 4 +- integration-tests/actions/actions.go | 102 ++++++++ .../actions/vrf/vrfv2/contract_steps.go | 10 +- .../actions/vrf/vrfv2plus/contract_steps.go | 8 +- integration-tests/load/vrfv2/gun.go | 2 +- integration-tests/load/vrfv2plus/gun.go | 2 +- integration-tests/smoke/vrfv2_test.go | 227 +++++++++++++++- integration-tests/smoke/vrfv2plus_test.go | 245 ++++++++++++++++-- 8 files changed, 558 insertions(+), 42 deletions(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 3ba0f2976ec..1f3e093cfdc 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -563,12 +563,12 @@ jobs: pyroscope_env: ci-smoke-vrf-evm-simulated - name: vrfv2 id: vrfv2 - nodes: 4 + nodes: 5 os: ubuntu-latest pyroscope_env: ci-smoke-vrf2-evm-simulated - name: vrfv2plus id: vrfv2plus - nodes: 7 + nodes: 8 os: ubuntu-latest pyroscope_env: ci-smoke-vrf2plus-evm-simulated - name: forwarder_ocr diff --git a/integration-tests/actions/actions.go b/integration-tests/actions/actions.go index f5c91b63527..ee4309c3613 100644 --- a/integration-tests/actions/actions.go +++ b/integration-tests/actions/actions.go @@ -8,14 +8,18 @@ import ( "errors" "fmt" "math/big" + "os" "strings" "sync" "testing" "time" "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/go-resty/resty/v2" + "github.com/rs/zerolog" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/keystore" @@ -33,6 +37,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" + "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" ) // ContractDeploymentInterval After how many contract actions to wait before starting any more @@ -562,3 +567,100 @@ func WaitForBlockNumberToBe( } } } + +// todo - move to EVMClient +func RewindSimulatedChainToBlockNumber( + ctx context.Context, + evmClient blockchain.EVMClient, + rpcURL string, + rewindChainToBlockNumber uint64, + l zerolog.Logger, +) (uint64, error) { + latestBlockNumberBeforeReorg, err := evmClient.LatestBlockNumber(ctx) + if err != nil { + return 0, fmt.Errorf("error getting latest block number: %w", err) + } + + l.Info(). + Str("RPC URL", rpcURL). + Uint64("Latest Block Number before Reorg", latestBlockNumberBeforeReorg). + Uint64("Rewind Chain to Block Number", rewindChainToBlockNumber). + Msg("Performing Reorg on chain by rewinding chain to specific block number") + + _, err = NewRPCRawClient(rpcURL).SetHeadForSimulatedChain(rewindChainToBlockNumber) + + if err != nil { + return 0, fmt.Errorf("error making reorg: %w", err) + } + + err = evmClient.WaitForEvents() + if err != nil { + return 0, fmt.Errorf("error waiting for events: %w", err) + } + + latestBlockNumberAfterReorg, err := evmClient.LatestBlockNumber(ctx) + if err != nil { + return 0, fmt.Errorf("error getting latest block number: %w", err) + } + + l.Info(). + Uint64("Block Number", latestBlockNumberAfterReorg). + Msg("Latest Block Number after Reorg") + return latestBlockNumberAfterReorg, nil +} + +func GetRPCUrl(env *test_env.CLClusterTestEnv, chainID int64) (string, error) { + provider, err := env.GetRpcProvider(chainID) + if err != nil { + return "", err + } + return provider.PublicHttpUrls()[0], nil +} + +// RPCRawClient +// created separate client since method evmClient.RawJsonRPCCall fails on "invalid argument 0: json: cannot unmarshal non-string into Go value of type hexutil.Uint64" +type RPCRawClient struct { + resty *resty.Client +} + +func NewRPCRawClient(url string) *RPCRawClient { + isDebug := os.Getenv("DEBUG_RESTY") == "true" + restyClient := resty.New().SetDebug(isDebug).SetBaseURL(url) + return &RPCRawClient{ + resty: restyClient, + } +} + +func (g *RPCRawClient) SetHeadForSimulatedChain(setHeadToBlockNumber uint64) (JsonRPCResponse, error) { + var responseObject JsonRPCResponse + postBody, _ := json.Marshal(map[string]any{ + "jsonrpc": "2.0", + "id": 1, + "method": "debug_setHead", + "params": []string{hexutil.EncodeUint64(setHeadToBlockNumber)}, + }) + resp, err := g.resty.R(). + SetHeader("Content-Type", "application/json"). + SetBody(postBody). + SetResult(&responseObject). + Post("") + + if err != nil { + return JsonRPCResponse{}, fmt.Errorf("error making API request: %w", err) + } + statusCode := resp.StatusCode() + if statusCode != 200 && statusCode != 201 { + return JsonRPCResponse{}, fmt.Errorf("error invoking debug_setHead method, received unexpected status code %d: %s", statusCode, resp.String()) + } + if responseObject.Error != "" { + return JsonRPCResponse{}, fmt.Errorf("received non-empty error field: %v", responseObject.Error) + } + return responseObject, nil +} + +type JsonRPCResponse struct { + Version string `json:"jsonrpc"` + Id int `json:"id"` + Result string `json:"result,omitempty"` + Error string `json:"error,omitempty"` +} diff --git a/integration-tests/actions/vrf/vrfv2/contract_steps.go b/integration-tests/actions/vrf/vrfv2/contract_steps.go index fef780b695b..7c1ee634f98 100644 --- a/integration-tests/actions/vrf/vrfv2/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2/contract_steps.go @@ -506,7 +506,7 @@ func RequestRandomnessAndWaitForFulfillment( randomnessRequestCountPerRequest uint16, randomnessRequestCountPerRequestDeviation uint16, randomWordsFulfilledEventTimeout time.Duration, -) (*contracts.CoordinatorRandomWordsFulfilled, error) { +) (*contracts.CoordinatorRandomWordsRequested, *contracts.CoordinatorRandomWordsFulfilled, error) { randomWordsRequestedEvent, err := RequestRandomness( l, consumer, @@ -520,18 +520,18 @@ func RequestRandomnessAndWaitForFulfillment( randomnessRequestCountPerRequestDeviation, ) if err != nil { - return nil, err + return nil, nil, err } - fulfillmentEvents, err := WaitRandomWordsFulfilledEvent( + randomWordsFulfilledEvent, err := WaitRandomWordsFulfilledEvent( coordinator, randomWordsRequestedEvent.RequestId, randomWordsFulfilledEventTimeout, l, ) if err != nil { - return nil, err + return nil, nil, err } - return fulfillmentEvents, nil + return randomWordsRequestedEvent, randomWordsFulfilledEvent, nil } func RequestRandomness( diff --git a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go index 143b1e2cd9b..26532e9b8e8 100644 --- a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go @@ -376,7 +376,7 @@ func RequestRandomnessAndWaitForFulfillment( isNativeBilling bool, config *vrfv2plus_config.General, l zerolog.Logger, -) (*contracts.CoordinatorRandomWordsFulfilled, error) { +) (*contracts.CoordinatorRandomWordsRequested, *contracts.CoordinatorRandomWordsFulfilled, error) { randomWordsRequestedEvent, err := RequestRandomness( consumer, coordinator, @@ -387,7 +387,7 @@ func RequestRandomnessAndWaitForFulfillment( l, ) if err != nil { - return nil, err + return nil, nil, err } randomWordsFulfilledEvent, err := WaitRandomWordsFulfilledEvent( @@ -399,9 +399,9 @@ func RequestRandomnessAndWaitForFulfillment( l, ) if err != nil { - return nil, err + return nil, nil, err } - return randomWordsFulfilledEvent, nil + return randomWordsRequestedEvent, randomWordsFulfilledEvent, nil } diff --git a/integration-tests/load/vrfv2/gun.go b/integration-tests/load/vrfv2/gun.go index 71d3113e60f..d15ee18d451 100644 --- a/integration-tests/load/vrfv2/gun.go +++ b/integration-tests/load/vrfv2/gun.go @@ -87,7 +87,7 @@ func (m *SingleHashGun) Call(_ *wasp.Generator) *wasp.Response { vrfv2Config := m.testConfig.General //randomly increase/decrease randomness request count per TX randomnessRequestCountPerRequest := deviateValue(*vrfv2Config.RandomnessRequestCountPerRequest, *vrfv2Config.RandomnessRequestCountPerRequestDeviation) - _, err := vrfv2.RequestRandomnessAndWaitForFulfillment( + _, _, err := vrfv2.RequestRandomnessAndWaitForFulfillment( m.logger, //the same consumer is used for all requests and in all subs m.contracts.VRFV2Consumers[0], diff --git a/integration-tests/load/vrfv2plus/gun.go b/integration-tests/load/vrfv2plus/gun.go index 8a99392fa57..6879fbe32dc 100644 --- a/integration-tests/load/vrfv2plus/gun.go +++ b/integration-tests/load/vrfv2plus/gun.go @@ -99,7 +99,7 @@ func (m *SingleHashGun) Call(_ *wasp.Generator) *wasp.Response { //randomly increase/decrease randomness request count per TX reqCount := deviateValue(*m.testConfig.General.RandomnessRequestCountPerRequest, *m.testConfig.General.RandomnessRequestCountPerRequestDeviation) m.testConfig.General.RandomnessRequestCountPerRequest = &reqCount - _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( //the same consumer is used for all requests and in all subs m.contracts.VRFV2PlusConsumer[0], m.contracts.CoordinatorV2Plus, diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go index 62c5dc84fe6..4dd23bce26f 100644 --- a/integration-tests/smoke/vrfv2_test.go +++ b/integration-tests/smoke/vrfv2_test.go @@ -63,7 +63,7 @@ func TestVRFv2Basic(t *testing.T) { } } if !*vrfv2Config.General.UseExistingEnv { - if err := testEnv.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := testEnv.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -104,7 +104,7 @@ func TestVRFv2Basic(t *testing.T) { subBalanceBeforeRequest := subscription.Balance // test and assert - randomWordsFulfilledEvent, err := vrfv2.RequestRandomnessAndWaitForFulfillment( + _, randomWordsFulfilledEvent, err := vrfv2.RequestRandomnessAndWaitForFulfillment( l, consumers[0], vrfContracts.CoordinatorV2, @@ -137,6 +137,54 @@ func TestVRFv2Basic(t *testing.T) { } }) + t.Run("VRF Node waits block confirmation number specified by the consumer in the rand request before sending fulfilment on-chain", func(t *testing.T) { + configCopy := config.MustCopy().(tc.TestConfig) + testConfig := configCopy.VRFv2.General + + consumers, subIDs, err := vrfv2.SetupNewConsumersAndSubs( + testEnv, + chainID, + vrfContracts.CoordinatorV2, + configCopy, + vrfContracts.LinkToken, + 1, + 1, + l, + ) + require.NoError(t, err, "error setting up new consumers and subs") + subID := subIDs[0] + subscription, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subID) + require.NoError(t, err, "error getting subscription information") + vrfcommon.LogSubDetails(l, subscription, strconv.FormatUint(subID, 10), vrfContracts.CoordinatorV2) + subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) + + expectedBlockNumberWait := uint16(10) + testConfig.MinimumConfirmations = ptr.Ptr[uint16](expectedBlockNumberWait) + randomWordsRequestedEvent, randomWordsFulfilledEvent, err := vrfv2.RequestRandomnessAndWaitForFulfillment( + l, + consumers[0], + vrfContracts.CoordinatorV2, + subID, + vrfKey, + *testConfig.MinimumConfirmations, + *testConfig.CallbackGasLimit, + *testConfig.NumberOfWords, + *testConfig.RandomnessRequestCountPerRequest, + *testConfig.RandomnessRequestCountPerRequestDeviation, + testConfig.RandomWordsFulfilledEventTimeout.Duration, + ) + require.NoError(t, err, "error requesting randomness and waiting for fulfilment") + + // check that VRF node waited at least the number of blocks specified by the consumer in the rand request min confs field + blockNumberWait := randomWordsRequestedEvent.Raw.BlockNumber - randomWordsFulfilledEvent.Raw.BlockNumber + require.GreaterOrEqual(t, blockNumberWait, uint64(expectedBlockNumberWait)) + + status, err := consumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId) + require.NoError(t, err, "error getting rand request status") + require.True(t, status.Fulfilled) + l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") + }) + t.Run("CL Node VRF Job Runs", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) consumers, subIDsForJobRuns, err := vrfv2.SetupNewConsumersAndSubs( @@ -161,7 +209,7 @@ func TestVRFv2Basic(t *testing.T) { require.NoError(t, err, "error reading job runs") // test and assert - _, err = vrfv2.RequestRandomnessAndWaitForFulfillment( + _, _, err = vrfv2.RequestRandomnessAndWaitForFulfillment( l, consumers[0], vrfContracts.CoordinatorV2, @@ -281,7 +329,7 @@ func TestVRFv2Basic(t *testing.T) { vrfcommon.LogSubDetails(l, subscription, strconv.FormatUint(subIDForOracleWithdraw, 10), vrfContracts.CoordinatorV2) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDsForOracleWithDraw...) - fulfilledEventLink, err := vrfv2.RequestRandomnessAndWaitForFulfillment( + _, fulfilledEventLink, err := vrfv2.RequestRandomnessAndWaitForFulfillment( l, consumers[0], vrfContracts.CoordinatorV2, @@ -436,7 +484,7 @@ func TestVRFv2Basic(t *testing.T) { // Request randomness - should fail due to underfunded subscription randomWordsFulfilledEventTimeout := 5 * time.Second - _, err = vrfv2.RequestRandomnessAndWaitForFulfillment( + _, _, err = vrfv2.RequestRandomnessAndWaitForFulfillment( l, consumers[0], vrfContracts.CoordinatorV2, @@ -556,7 +604,7 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { } } if !*vrfv2Config.General.UseExistingEnv { - if err := testEnv.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := testEnv.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -602,7 +650,7 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { var fulfillmentTxFromAddresses []string for i := 0; i < newEnvConfig.NumberOfTxKeysToCreate+1; i++ { - randomWordsFulfilledEvent, err := vrfv2.RequestRandomnessAndWaitForFulfillment( + _, randomWordsFulfilledEvent, err := vrfv2.RequestRandomnessAndWaitForFulfillment( l, consumers[0], vrfContracts.CoordinatorV2, @@ -664,7 +712,7 @@ func TestVRFOwner(t *testing.T) { } } if !*vrfv2Config.General.UseExistingEnv { - if err := testEnv.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := testEnv.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -807,7 +855,7 @@ func TestVRFV2WithBHS(t *testing.T) { } } if !*vrfv2Config.General.UseExistingEnv { - if err := testEnv.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := testEnv.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -984,3 +1032,164 @@ func TestVRFV2WithBHS(t *testing.T) { require.Equal(t, 0, randomWordsRequestedEvent.Raw.BlockHash.Cmp(randRequestBlockHash)) }) } + +func TestVRFV2NodeReorg(t *testing.T) { + t.Parallel() + var ( + env *test_env.CLClusterTestEnv + vrfContracts *vrfcommon.VRFContracts + subIDsForCancellingAfterTest []uint64 + defaultWalletAddress string + vrfKey *vrfcommon.VRFKeyData + ) + l := logging.GetTestLogger(t) + + config, err := tc.GetConfig("Smoke", tc.VRFv2) + require.NoError(t, err, "Error getting config") + vrfv2Config := config.VRFv2 + chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID + + cleanupFn := func() { + evmClient, err := env.GetEVMClient(chainID) + require.NoError(t, err, "Getting EVM client shouldn't fail") + + if evmClient.NetworkSimulated() { + l.Info(). + Str("Network Name", evmClient.GetNetworkName()). + Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") + } else { + if *vrfv2Config.General.CancelSubsAfterTestRun { + //cancel subs and return funds to sub owner + vrfv2.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, defaultWalletAddress, subIDsForCancellingAfterTest, l) + } + } + if !*vrfv2Config.General.UseExistingEnv { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { + l.Error().Err(err).Msg("Error cleaning up test environment") + } + } + } + newEnvConfig := vrfcommon.NewEnvConfig{ + NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF}, + NumberOfTxKeysToCreate: 0, + UseVRFOwner: false, + UseTestCoordinator: false, + } + + env, vrfContracts, vrfKey, _, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, config, chainID, cleanupFn, newEnvConfig, l) + require.NoError(t, err, "Error setting up VRFv2 universe") + + evmClient, err := env.GetEVMClient(chainID) + require.NoError(t, err, "Getting EVM client shouldn't fail") + defaultWalletAddress = evmClient.GetDefaultWallet().Address() + + consumers, subIDs, err := vrfv2.SetupNewConsumersAndSubs( + env, + chainID, + vrfContracts.CoordinatorV2, + config, + vrfContracts.LinkToken, + 1, + 1, + l, + ) + require.NoError(t, err, "error setting up new consumers and subs") + subID := subIDs[0] + subscription, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subID) + require.NoError(t, err, "error getting subscription information") + vrfcommon.LogSubDetails(l, subscription, strconv.FormatUint(subID, 10), vrfContracts.CoordinatorV2) + subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) + + t.Run("Reorg on fulfillment", func(t *testing.T) { + configCopy := config.MustCopy().(tc.TestConfig) + configCopy.VRFv2.General.MinimumConfirmations = ptr.Ptr[uint16](10) + + //1. request randomness and wait for fulfillment for blockhash from Reorged Fork + randomWordsRequestedEvent, randomWordsFulfilledEventOnReorgedFork, err := vrfv2.RequestRandomnessAndWaitForFulfillment( + l, + consumers[0], + vrfContracts.CoordinatorV2, + subID, + vrfKey, + *configCopy.VRFv2.General.MinimumConfirmations, + *configCopy.VRFv2.General.CallbackGasLimit, + *configCopy.VRFv2.General.NumberOfWords, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequestDeviation, + configCopy.VRFv2.General.RandomWordsFulfilledEventTimeout.Duration, + ) + require.NoError(t, err) + + // rewind chain to block number after the request was made, but before the request was fulfilled + rewindChainToBlock := randomWordsRequestedEvent.Raw.BlockNumber + 1 + + rpcUrl, err := actions.GetRPCUrl(env, chainID) + require.NoError(t, err, "error getting rpc url") + + //2. rewind chain by n number of blocks - basically, mimicking reorg scenario + latestBlockNumberAfterReorg, err := actions.RewindSimulatedChainToBlockNumber(testcontext.Get(t), evmClient, rpcUrl, rewindChainToBlock, l) + require.NoError(t, err, fmt.Sprintf("error rewinding chain to block number %d", rewindChainToBlock)) + + //3.1 ensure that chain is reorged and latest block number is greater than the block number when request was made + require.Greater(t, latestBlockNumberAfterReorg, randomWordsRequestedEvent.Raw.BlockNumber) + + //3.2 ensure that chain is reorged and latest block number is less than the block number when fulfilment was performed + require.Less(t, latestBlockNumberAfterReorg, randomWordsFulfilledEventOnReorgedFork.Raw.BlockNumber) + + //4. wait for the fulfillment which VRF Node will generate for Canonical chain + _, err = vrfv2.WaitRandomWordsFulfilledEvent( + vrfContracts.CoordinatorV2, + randomWordsRequestedEvent.RequestId, + configCopy.VRFv2.General.RandomWordsFulfilledEventTimeout.Duration, + l, + ) + + require.NoError(t, err, "error waiting for randomness fulfilled event") + }) + + t.Run("Reorg on rand request", func(t *testing.T) { + configCopy := config.MustCopy().(tc.TestConfig) + //1. set minimum confirmations to higher value so that we can be sure that request won't be fulfilled before reorg + configCopy.VRFv2.General.MinimumConfirmations = ptr.Ptr[uint16](6) + + //2. request randomness + randomWordsRequestedEvent, err := vrfv2.RequestRandomness( + l, + consumers[0], + vrfContracts.CoordinatorV2, + subID, + vrfKey, + *configCopy.VRFv2.General.MinimumConfirmations, + *configCopy.VRFv2.General.CallbackGasLimit, + *configCopy.VRFv2.General.NumberOfWords, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequest, + *configCopy.VRFv2.General.RandomnessRequestCountPerRequestDeviation, + ) + require.NoError(t, err) + + // rewind chain to block number before the randomness request was made + rewindChainToBlockNumber := randomWordsRequestedEvent.Raw.BlockNumber - 3 + + rpcUrl, err := actions.GetRPCUrl(env, chainID) + require.NoError(t, err, "error getting rpc url") + + //3. rewind chain by n number of blocks - basically, mimicking reorg scenario + latestBlockNumberAfterReorg, err := actions.RewindSimulatedChainToBlockNumber(testcontext.Get(t), evmClient, rpcUrl, rewindChainToBlockNumber, l) + require.NoError(t, err, fmt.Sprintf("error rewinding chain to block number %d", rewindChainToBlockNumber)) + + //4. ensure that chain is reorged and latest block number is less than the block number when request was made + require.Less(t, latestBlockNumberAfterReorg, randomWordsRequestedEvent.Raw.BlockNumber) + + //5. ensure that rand request is not fulfilled for the request which was made on reorged fork + // For context - when performing debug_setHead on geth simulated chain and therefore rewinding chain to a previous block, + //then tx that was mined after reorg will not appear in canonical chain contrary to real world scenario + //Hence, we only verify that VRF node will not generate fulfillment for the reorged fork request + _, err = vrfContracts.CoordinatorV2.WaitForRandomWordsFulfilledEvent( + contracts.RandomWordsFulfilledEventFilter{ + RequestIds: []*big.Int{randomWordsRequestedEvent.RequestId}, + Timeout: time.Second * 10, + }, + ) + require.Error(t, err, "fulfillment should not be generated for the request which was made on reorged fork on Simulated Chain") + }) +} diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go index c535e77ef62..ae190e060ee 100644 --- a/integration-tests/smoke/vrfv2plus_test.go +++ b/integration-tests/smoke/vrfv2plus_test.go @@ -19,6 +19,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv2plus" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -26,7 +27,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store" - "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" it_utils "github.com/smartcontractkit/chainlink/integration-tests/utils" @@ -64,7 +64,7 @@ func TestVRFv2Plus(t *testing.T) { } } if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -106,7 +106,7 @@ func TestVRFv2Plus(t *testing.T) { subBalanceBeforeRequest := subscription.Balance // test and assert - randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -163,7 +163,7 @@ func TestVRFv2Plus(t *testing.T) { subNativeTokenBalanceBeforeRequest := subscription.NativeBalance // test and assert - randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -193,6 +193,52 @@ func TestVRFv2Plus(t *testing.T) { require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") } }) + + t.Run("VRF Node waits block confirmation number specified by the consumer in the rand request before sending fulfilment on-chain", func(t *testing.T) { + configCopy := config.MustCopy().(tc.TestConfig) + testConfig := configCopy.VRFv2Plus.General + var isNativeBilling = true + + consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( + env, + chainID, + vrfContracts.CoordinatorV2Plus, + configCopy, + vrfContracts.LinkToken, + 1, + 1, + l, + ) + require.NoError(t, err, "error setting up new consumers and subs") + subID := subIDs[0] + subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) + require.NoError(t, err, "error getting subscription information") + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) + subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) + + expectedBlockNumberWait := uint16(10) + testConfig.MinimumConfirmations = ptr.Ptr[uint16](expectedBlockNumberWait) + randomWordsRequestedEvent, randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + consumers[0], + vrfContracts.CoordinatorV2Plus, + vrfKey, + subID, + isNativeBilling, + testConfig, + l, + ) + require.NoError(t, err, "error requesting randomness and waiting for fulfilment") + + // check that VRF node waited at least the number of blocks specified by the consumer in the rand request min confs field + blockNumberWait := randomWordsRequestedEvent.Raw.BlockNumber - randomWordsFulfilledEvent.Raw.BlockNumber + require.GreaterOrEqual(t, blockNumberWait, uint64(expectedBlockNumberWait)) + + status, err := consumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId) + require.NoError(t, err, "error getting rand request status") + require.True(t, status.Fulfilled) + l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") + }) + t.Run("CL Node VRF Job Runs", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) var isNativeBilling = false @@ -217,7 +263,7 @@ func TestVRFv2Plus(t *testing.T) { require.NoError(t, err, "error reading job runs") // test and assert - _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -482,7 +528,7 @@ func TestVRFv2Plus(t *testing.T) { require.False(t, pendingRequestsExist, "Pending requests should not exist") configCopy.VRFv2Plus.General.RandomWordsFulfilledEventTimeout = ptr.Ptr(blockchain.StrDuration{Duration: 5 * time.Second}) - _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -494,7 +540,7 @@ func TestVRFv2Plus(t *testing.T) { require.Error(t, err, "error should occur for waiting for fulfilment due to low sub balance") - _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -622,7 +668,7 @@ func TestVRFv2Plus(t *testing.T) { vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) - fulfilledEventLink, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, fulfilledEventLink, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -633,7 +679,7 @@ func TestVRFv2Plus(t *testing.T) { ) require.NoError(t, err) - fulfilledEventNative, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, fulfilledEventNative, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -719,7 +765,7 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { } } if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -766,7 +812,7 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { var fulfillmentTxFromAddresses []string for i := 0; i < newEnvConfig.NumberOfTxKeysToCreate+1; i++ { - randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -826,7 +872,7 @@ func TestVRFv2PlusMigration(t *testing.T) { } } if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -1002,7 +1048,7 @@ func TestVRFv2PlusMigration(t *testing.T) { require.Equal(t, 0, expectedEthTotalBalanceForOldCoordinator.Cmp(oldCoordinatorEthTotalBalanceAfterMigration)) //Verify rand requests fulfills with Link Token billing - _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], newCoordinator, vrfKey, @@ -1014,7 +1060,7 @@ func TestVRFv2PlusMigration(t *testing.T) { require.NoError(t, err, "error requesting randomness and waiting for fulfilment") //Verify rand requests fulfills with Native Token billing - _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[1], newCoordinator, vrfKey, @@ -1249,7 +1295,7 @@ func TestVRFV2PlusWithBHS(t *testing.T) { } } if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -1470,7 +1516,7 @@ func TestVRFV2PlusWithBHF(t *testing.T) { } } if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -1618,7 +1664,7 @@ func TestVRFv2PlusReplayAfterTimeout(t *testing.T) { } } if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -1694,7 +1740,7 @@ func TestVRFv2PlusReplayAfterTimeout(t *testing.T) { 1, ) require.NoError(t, err, "error creating funded sub in replay test") - randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[1], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -1817,7 +1863,7 @@ func TestVRFv2PlusPendingBlockSimulationAndZeroConfirmationDelays(t *testing.T) } } if !*vrfv2PlusConfig.General.UseExistingEnv { - if err := env.Cleanup(test_env.CleanupOpts{}); err != nil { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { l.Error().Err(err).Msg("Error cleaning up test environment") } } @@ -1862,7 +1908,7 @@ func TestVRFv2PlusPendingBlockSimulationAndZeroConfirmationDelays(t *testing.T) l.Info().Uint16("minimumConfirmationDelay", *config.VRFv2Plus.General.MinimumConfirmations).Msg("Minimum Confirmation Delay") // test and assert - randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + _, randomWordsFulfilledEvent, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -1878,3 +1924,162 @@ func TestVRFv2PlusPendingBlockSimulationAndZeroConfirmationDelays(t *testing.T) require.True(t, status.Fulfilled) l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") } + +func TestVRFv2PlusNodeReorg(t *testing.T) { + t.Parallel() + var ( + env *test_env.CLClusterTestEnv + vrfContracts *vrfcommon.VRFContracts + subIDsForCancellingAfterTest []*big.Int + defaultWalletAddress string + vrfKey *vrfcommon.VRFKeyData + ) + l := logging.GetTestLogger(t) + + config, err := tc.GetConfig("Smoke", tc.VRFv2Plus) + require.NoError(t, err, "Error getting config") + vrfv2PlusConfig := config.VRFv2Plus + chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID + + cleanupFn := func() { + evmClient, err := env.GetEVMClient(chainID) + require.NoError(t, err, "Getting EVM client shouldn't fail") + + if evmClient.NetworkSimulated() { + l.Info(). + Str("Network Name", evmClient.GetNetworkName()). + Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") + } else { + if *vrfv2PlusConfig.General.CancelSubsAfterTestRun { + //cancel subs and return funds to sub owner + vrfv2plus.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, defaultWalletAddress, subIDsForCancellingAfterTest, l) + } + } + if !*vrfv2PlusConfig.General.UseExistingEnv { + if err := env.Cleanup(test_env.CleanupOpts{TestName: t.Name()}); err != nil { + l.Error().Err(err).Msg("Error cleaning up test environment") + } + } + } + newEnvConfig := vrfcommon.NewEnvConfig{ + NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF}, + NumberOfTxKeysToCreate: 0, + UseVRFOwner: false, + UseTestCoordinator: false, + } + + env, vrfContracts, vrfKey, _, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, config, chainID, cleanupFn, newEnvConfig, l) + require.NoError(t, err, "Error setting up VRFv2Plus universe") + + evmClient, err := env.GetEVMClient(chainID) + require.NoError(t, err, "Getting EVM client shouldn't fail") + defaultWalletAddress = evmClient.GetDefaultWallet().Address() + + var isNativeBilling = true + + consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( + env, + chainID, + vrfContracts.CoordinatorV2Plus, + config, + vrfContracts.LinkToken, + 1, + 1, + l, + ) + require.NoError(t, err, "error setting up new consumers and subs") + subID := subIDs[0] + subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) + require.NoError(t, err, "error getting subscription information") + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) + subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) + + t.Run("Reorg on fulfillment", func(t *testing.T) { + configCopy := config.MustCopy().(tc.TestConfig) + configCopy.VRFv2Plus.General.MinimumConfirmations = ptr.Ptr[uint16](10) + + //1. request randomness and wait for fulfillment for blockhash from Reorged Fork + randomWordsRequestedEvent, randomWordsFulfilledEventOnReorgedFork, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( + consumers[0], + vrfContracts.CoordinatorV2Plus, + vrfKey, + subID, + isNativeBilling, + configCopy.VRFv2Plus.General, + l, + ) + require.NoError(t, err) + + // rewind chain to block number after the request was made, but before the request was fulfilled + rewindChainToBlock := randomWordsRequestedEvent.Raw.BlockNumber + 1 + + rpcUrl, err := actions.GetRPCUrl(env, chainID) + require.NoError(t, err, "error getting rpc url") + + //2. rewind chain by n number of blocks - basically, mimicking reorg scenario + latestBlockNumberAfterReorg, err := actions.RewindSimulatedChainToBlockNumber(testcontext.Get(t), evmClient, rpcUrl, rewindChainToBlock, l) + require.NoError(t, err, fmt.Sprintf("error rewinding chain to block number %d", rewindChainToBlock)) + + //3.1 ensure that chain is reorged and latest block number is greater than the block number when request was made + require.Greater(t, latestBlockNumberAfterReorg, randomWordsRequestedEvent.Raw.BlockNumber) + + //3.2 ensure that chain is reorged and latest block number is less than the block number when fulfilment was performed + require.Less(t, latestBlockNumberAfterReorg, randomWordsFulfilledEventOnReorgedFork.Raw.BlockNumber) + + //4. wait for the fulfillment which VRF Node will generate for Canonical chain + _, err = vrfv2plus.WaitRandomWordsFulfilledEvent( + vrfContracts.CoordinatorV2Plus, + randomWordsRequestedEvent.RequestId, + subID, + isNativeBilling, + configCopy.VRFv2Plus.General.RandomWordsFulfilledEventTimeout.Duration, + l, + ) + require.NoError(t, err, "error waiting for randomness fulfilled event") + }) + + t.Run("Reorg on rand request", func(t *testing.T) { + configCopy := config.MustCopy().(tc.TestConfig) + //1. set minimum confirmations to higher value so that we can be sure that request won't be fulfilled before reorg + configCopy.VRFv2Plus.General.MinimumConfirmations = ptr.Ptr[uint16](6) + + //2. request randomness + randomWordsRequestedEvent, err := vrfv2plus.RequestRandomness( + consumers[0], + vrfContracts.CoordinatorV2Plus, + vrfKey, + subID, + isNativeBilling, + configCopy.VRFv2Plus.General, + l, + ) + require.NoError(t, err) + + // rewind chain to block number before the randomness request was made + rewindChainToBlockNumber := randomWordsRequestedEvent.Raw.BlockNumber - 3 + + rpcUrl, err := actions.GetRPCUrl(env, chainID) + require.NoError(t, err, "error getting rpc url") + + //3. rewind chain by n number of blocks - basically, mimicking reorg scenario + latestBlockNumberAfterReorg, err := actions.RewindSimulatedChainToBlockNumber(testcontext.Get(t), evmClient, rpcUrl, rewindChainToBlockNumber, l) + require.NoError(t, err, fmt.Sprintf("error rewinding chain to block number %d", rewindChainToBlockNumber)) + + //4. ensure that chain is reorged and latest block number is less than the block number when request was made + require.Less(t, latestBlockNumberAfterReorg, randomWordsRequestedEvent.Raw.BlockNumber) + + //5. ensure that rand request is not fulfilled for the request which was made on reorged fork + // For context - when performing debug_setHead on geth simulated chain and therefore rewinding chain to a previous block, + //then tx that was mined after reorg will not appear in canonical chain contrary to real world scenario + //Hence, we only verify that VRF node will not generate fulfillment for the reorged fork request + _, err = vrfContracts.CoordinatorV2Plus.WaitForRandomWordsFulfilledEvent( + contracts.RandomWordsFulfilledEventFilter{ + RequestIds: []*big.Int{randomWordsRequestedEvent.RequestId}, + SubIDs: []*big.Int{subID}, + Timeout: time.Second * 10, + }, + ) + require.Error(t, err, "fulfillment should not be generated for the request which was made on reorged fork on Simulated Chain") + }) + +} From 758ffd6da097adac1f49ceded5e0998cdcb98a29 Mon Sep 17 00:00:00 2001 From: frank zhu Date: Wed, 24 Apr 2024 09:38:51 -0700 Subject: [PATCH 05/34] fix: add changeset semvar value check (#12947) * fix: add changeset semvar value check * add #internal tag --- .changeset/pretty-kangaroos-tell.md | 5 +++++ .github/scripts/check-changeset-tags.sh | 8 ++++++++ 2 files changed, 13 insertions(+) create mode 100644 .changeset/pretty-kangaroos-tell.md diff --git a/.changeset/pretty-kangaroos-tell.md b/.changeset/pretty-kangaroos-tell.md new file mode 100644 index 00000000000..946869b1ca0 --- /dev/null +++ b/.changeset/pretty-kangaroos-tell.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Add check for valid semvar value for changeset file #internal diff --git a/.github/scripts/check-changeset-tags.sh b/.github/scripts/check-changeset-tags.sh index 579661fe704..f82c16d5769 100755 --- a/.github/scripts/check-changeset-tags.sh +++ b/.github/scripts/check-changeset-tags.sh @@ -29,6 +29,14 @@ if [[ ! -f "$CHANGESET_FILE_PATH" ]]; then exit 1 fi +changeset_content=$(sed -n '/^---$/,/^---$/{ /^---$/!p; }' $CHANGESET_FILE_PATH) +semvar_value=$(echo "$changeset_content" | awk -F": " '/"chainlink"/ {print $2}') + +if [[ "$semvar_value" != "major" && "$semvar_value" != "minor" && "$semvar_value" != "patch" ]]; then + echo "Invalid changeset semvar value for 'chainlink'. Must be 'major', 'minor', or 'patch'." + exit 1 +fi + while IFS= read -r line; do for tag in "${tags_list[@]}"; do if [[ "$line" == *"$tag"* ]]; then From 78dd3e026a81cb656b99ac62ce552369573ca736 Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Wed, 24 Apr 2024 15:45:08 -0500 Subject: [PATCH 06/34] use sqlutil instead of pg.QOpts/Q/Queryer (#12456) * use sqlutil instead of pg.QOpts * changeset --- .changeset/fuzzy-pans-destroy.md | 5 + core/bridges/orm_test.go | 2 +- core/chains/evm/log/helpers_test.go | 13 +- core/chains/evm/log/integration_test.go | 8 +- core/chains/evm/logpoller/observability.go | 4 +- core/chains/evm/logpoller/orm.go | 208 ++- core/chains/evm/logpoller/query.go | 2 +- core/chains/evm/txmgr/broadcaster_test.go | 2 +- core/chains/evm/txmgr/builder.go | 9 +- core/chains/evm/txmgr/evm_tx_store.go | 52 +- core/chains/evm/txmgr/txmgr_test.go | 1 - core/chains/legacyevm/chain.go | 20 +- core/chains/legacyevm/chain_test.go | 3 +- core/chains/legacyevm/evm_txm.go | 8 +- core/cmd/eth_keys_commands_test.go | 4 +- core/cmd/evm_transaction_commands_test.go | 10 +- core/cmd/jobs_commands_test.go | 7 +- core/cmd/shell.go | 24 +- core/cmd/shell_local.go | 14 +- core/cmd/shell_local_test.go | 12 +- core/cmd/shell_remote_test.go | 13 +- core/internal/cltest/cltest.go | 54 +- core/internal/cltest/factories.go | 16 +- core/internal/cltest/job_factories.go | 23 +- core/internal/features/features_test.go | 19 +- .../features/ocr2/features_ocr2_test.go | 10 +- core/internal/mocks/application.go | 22 - core/internal/testutils/evmtest/evmtest.go | 7 +- core/internal/testutils/pgtest/pgtest.go | 25 +- core/internal/testutils/testutils.go | 3 +- core/scripts/gateway/run_gateway.go | 2 +- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 +- core/services/chainlink/application.go | 73 +- .../relayer_chain_interoperators_test.go | 13 +- core/services/chainlink/relayer_factory.go | 19 +- core/services/cron/cron_test.go | 4 +- core/services/directrequest/delegate.go | 33 +- core/services/directrequest/delegate_test.go | 7 +- core/services/feeds/mocks/orm.go | 1323 +++++++---------- core/services/feeds/mocks/service.go | 221 ++- core/services/feeds/orm.go | 247 +-- core/services/feeds/orm_test.go | 380 ++--- core/services/feeds/service.go | 299 ++-- core/services/feeds/service_test.go | 1057 +++++++------ core/services/fluxmonitorv2/delegate.go | 13 +- core/services/fluxmonitorv2/flux_monitor.go | 18 +- .../fluxmonitorv2/flux_monitor_test.go | 1 + .../fluxmonitorv2/integrations_test.go | 30 +- core/services/fluxmonitorv2/orm_test.go | 4 +- core/services/functions/listener_test.go | 4 +- core/services/gateway/delegate.go | 13 +- core/services/gateway/gateway_test.go | 12 +- core/services/gateway/handler_factory.go | 13 +- .../handlers/functions/handler.functions.go | 9 +- .../functions/handler.functions_test.go | 4 +- .../gateway_integration_test.go | 2 +- core/services/job/common.go | 3 - core/services/job/helpers_test.go | 3 +- core/services/job/job_orm_test.go | 311 ++-- .../job/job_pipeline_orm_integration_test.go | 6 +- core/services/job/kv_orm.go | 14 +- core/services/job/kv_orm_test.go | 9 +- core/services/job/mocks/orm.go | 458 +++--- core/services/job/mocks/spawner.go | 53 +- core/services/job/orm.go | 787 +++++----- core/services/job/orm_test.go | 8 +- core/services/job/runner_integration_test.go | 84 +- core/services/job/spawner.go | 56 +- core/services/job/spawner_test.go | 56 +- core/services/keeper/delegate.go | 19 +- core/services/keeper/helpers_test.go | 4 + core/services/keeper/integration_test.go | 8 +- .../registry_synchronizer_helper_test.go | 2 +- .../registry_synchronizer_process_logs.go | 3 + .../keeper/registry_synchronizer_sync.go | 6 +- core/services/keeper/upkeep_executer_test.go | 2 +- core/services/keystore/eth_test.go | 6 +- core/services/llo/delegate.go | 16 +- core/services/ocr/contract_tracker.go | 5 +- core/services/ocr/contract_tracker_test.go | 10 +- core/services/ocr/database.go | 7 +- core/services/ocr/database_test.go | 4 +- core/services/ocr/delegate.go | 15 +- core/services/ocr/helpers_internal_test.go | 7 +- .../ocr/mocks/ocr_contract_tracker_db.go | 31 +- core/services/ocr2/database.go | 39 +- core/services/ocr2/database_test.go | 36 +- core/services/ocr2/delegate.go | 63 +- .../ocr2/plugins/dkg/persistence/db.go | 19 +- .../ocr2/plugins/dkg/persistence/db_test.go | 2 +- core/services/ocr2/plugins/dkg/plugin.go | 8 +- .../generic/pipeline_runner_adapter_test.go | 4 +- core/services/ocr2/plugins/ocr2keeper/util.go | 13 +- core/services/ocrbootstrap/database.go | 11 +- core/services/ocrbootstrap/database_test.go | 8 +- core/services/ocrbootstrap/delegate.go | 13 +- .../services/ocrcommon/discoverer_database.go | 13 +- .../ocrcommon/discoverer_database_test.go | 2 +- core/services/ocrcommon/peer_wrapper.go | 13 +- core/services/ocrcommon/peer_wrapper_test.go | 14 +- core/services/pg/connection.go | 5 + core/services/pg/lease_lock.go | 9 +- core/services/pg/q.go | 384 ----- core/services/pg/q_test.go | 85 -- core/services/pg/sqlx.go | 24 +- core/services/pg/transaction.go | 95 -- core/services/pg/utils.go | 50 - core/services/pipeline/helpers_test.go | 3 +- core/services/pipeline/mocks/orm.go | 18 +- core/services/pipeline/orm.go | 69 +- core/services/pipeline/orm_test.go | 49 +- core/services/pipeline/runner.go | 2 +- core/services/pipeline/runner_test.go | 19 +- core/services/pipeline/task.bridge_test.go | 54 +- core/services/pipeline/task.http_test.go | 2 +- core/services/pipeline/test_helpers_test.go | 3 +- core/services/promreporter/prom_reporter.go | 10 +- .../promreporter/prom_reporter_test.go | 7 +- core/services/relay/evm/evm.go | 18 +- core/services/relay/evm/evm_test.go | 23 +- .../evm/mercury/wsrpc/pb/mercury_wsrpc.pb.go | 1 - core/services/relay/evm/ocr2keeper.go | 5 +- core/services/relay/evm/ocr2vrf.go | 6 +- core/services/versioning/orm.go | 14 +- core/services/versioning/orm_test.go | 7 +- core/services/vrf/delegate_test.go | 10 +- core/services/vrf/v1/integration_test.go | 28 +- core/services/vrf/v1/listener_v1.go | 9 +- .../vrf/v2/integration_helpers_test.go | 6 +- .../vrf/v2/integration_v2_plus_test.go | 24 +- .../v2/integration_v2_reverted_txns_test.go | 2 +- core/services/vrf/v2/integration_v2_test.go | 22 +- core/services/vrf/vrftesthelpers/helpers.go | 6 +- core/services/webhook/authorizer.go | 12 +- core/services/webhook/authorizer_test.go | 3 +- .../webhook/external_initiator_manager.go | 44 +- .../external_initiator_manager_test.go | 17 +- .../mocks/external_initiator_manager.go | 18 +- core/services/webhook/validate.go | 6 +- core/services/webhook/validate_test.go | 15 +- core/sessions/ldapauth/sync.go | 38 +- core/sessions/localauth/reaper.go | 16 +- core/sessions/localauth/reaper_test.go | 2 +- core/store/migrate/migrate.go | 39 +- core/store/migrate/migrate_test.go | 27 +- .../migrations/0054_remove_legacy_pipeline.go | 10 +- core/web/bridge_types_controller.go | 2 +- core/web/eth_keys_controller_test.go | 3 +- core/web/evm_transactions_controller_test.go | 8 +- core/web/evm_transfer_controller_test.go | 15 +- core/web/evm_tx_attempts_controller_test.go | 2 +- .../external_initiators_controller_test.go | 2 +- core/web/jobs_controller.go | 10 +- core/web/jobs_controller_test.go | 46 +- core/web/loader/feeds_manager.go | 4 +- core/web/loader/feeds_manager_chain_config.go | 4 +- core/web/loader/job.go | 8 +- core/web/loader/job_proposal.go | 4 +- core/web/loader/job_proposal_spec.go | 4 +- core/web/loader/job_run.go | 4 +- core/web/loader/job_spec_errors.go | 3 +- core/web/loader/loader_test.go | 16 +- ...ipeline_job_spec_errors_controller_test.go | 3 +- core/web/pipeline_runs_controller.go | 11 +- core/web/pipeline_runs_controller_test.go | 12 +- core/web/resolver/bridge_test.go | 4 +- .../feeds_manager_chain_config_test.go | 14 +- core/web/resolver/feeds_manager_test.go | 16 +- core/web/resolver/job.go | 4 +- core/web/resolver/job_error_test.go | 14 +- core/web/resolver/job_proposal_spec_test.go | 20 +- core/web/resolver/job_proposal_test.go | 7 +- core/web/resolver/job_run_test.go | 12 +- core/web/resolver/job_test.go | 36 +- core/web/resolver/mutation.go | 26 +- core/web/resolver/query.go | 14 +- core/web/resolver/spec_test.go | 29 +- core/web/sessions_controller_test.go | 26 +- go.mod | 2 +- go.sum | 4 +- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 +- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 +- 185 files changed, 3795 insertions(+), 4580 deletions(-) create mode 100644 .changeset/fuzzy-pans-destroy.md delete mode 100644 core/services/pg/q.go delete mode 100644 core/services/pg/q_test.go delete mode 100644 core/services/pg/transaction.go delete mode 100644 core/services/pg/utils.go diff --git a/.changeset/fuzzy-pans-destroy.md b/.changeset/fuzzy-pans-destroy.md new file mode 100644 index 00000000000..3cff19f8d8a --- /dev/null +++ b/.changeset/fuzzy-pans-destroy.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Use sqlutil instead of pg.Opts/Q/Queryer #internal diff --git a/core/bridges/orm_test.go b/core/bridges/orm_test.go index 85e8b9ecdef..b85b6be00dd 100644 --- a/core/bridges/orm_test.go +++ b/core/bridges/orm_test.go @@ -144,7 +144,7 @@ func TestORM_TestCachedResponse(t *testing.T) { orm := bridges.NewORM(db) trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(ctx, nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(ctx, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) _, err = orm.GetCachedResponse(ctx, "dot", specID, 1*time.Second) diff --git a/core/chains/evm/log/helpers_test.go b/core/chains/evm/log/helpers_test.go index 0d725b8594b..13aeb8d2338 100644 --- a/core/chains/evm/log/helpers_test.go +++ b/core/chains/evm/log/helpers_test.go @@ -110,7 +110,7 @@ func newBroadcasterHelperWithEthClient(t *testing.T, ethClient evmclient.Client, m[r.Chain().ID().String()] = r.Chain() } legacyChains := legacyevm.NewLegacyChains(m, cc.AppConfig().EVMConfigs()) - pipelineHelper := cltest.NewJobPipelineV2(t, globalConfig.WebServer(), globalConfig.JobPipeline(), globalConfig.Database(), legacyChains, db, kst, nil, nil) + pipelineHelper := cltest.NewJobPipelineV2(t, globalConfig.WebServer(), globalConfig.JobPipeline(), legacyChains, db, kst, nil, nil) return &broadcasterHelper{ t: t, @@ -263,7 +263,7 @@ func (helper *broadcasterHelper) newLogListenerWithJob(name string) *simpleLogLi PipelineSpec: &pipeline.Spec{}, ExternalJobID: uuid.New(), } - err := helper.pipelineHelper.Jrm.CreateJob(jb) + err := helper.pipelineHelper.Jrm.CreateJob(testutils.Context(t), jb) require.NoError(t, err) var rec received @@ -288,7 +288,7 @@ func (listener *simpleLogListener) HandleLog(ctx context.Context, lb log.Broadca listener.received.logs = append(listener.received.logs, lb.RawLog()) listener.received.broadcasts = append(listener.received.broadcasts, lb) - consumed := listener.handleLogBroadcast(lb) + consumed := listener.handleLogBroadcast(ctx, lb) if !consumed { listener.received.uniqueLogs = append(listener.received.uniqueLogs, lb.RawLog()) @@ -321,9 +321,8 @@ func (listener *simpleLogListener) requireAllReceived(t *testing.T, expectedStat }, testutils.WaitTimeout(t), time.Second, "len(received.uniqueLogs): %v is not equal len(expectedState.uniqueLogs): %v", len(received.getUniqueLogs()), len(expectedState.getUniqueLogs())) } -func (listener *simpleLogListener) handleLogBroadcast(lb log.Broadcast) bool { +func (listener *simpleLogListener) handleLogBroadcast(ctx context.Context, lb log.Broadcast) bool { t := listener.t - ctx := testutils.Context(t) consumed, err := listener.WasAlreadyConsumed(ctx, lb) if !assert.NoError(t, err) { return false @@ -354,8 +353,8 @@ type mockListener struct { jobID int32 } -func (l *mockListener) JobID() int32 { return l.jobID } -func (l *mockListener) HandleLog(log.Broadcast) {} +func (l *mockListener) JobID() int32 { return l.jobID } +func (l *mockListener) HandleLog(context.Context, log.Broadcast) {} type mockEthClientExpectedCalls struct { SubscribeFilterLogs int diff --git a/core/chains/evm/log/integration_test.go b/core/chains/evm/log/integration_test.go index fd6b375d80a..e34533b3cfb 100644 --- a/core/chains/evm/log/integration_test.go +++ b/core/chains/evm/log/integration_test.go @@ -250,7 +250,6 @@ func TestBroadcaster_ReplaysLogs(t *testing.T) { func TestBroadcaster_BackfillUnconsumedAfterCrash(t *testing.T) { contract1 := newMockContract(t) contract2 := newMockContract(t) - ctx := testutils.Context(t) blocks := cltest.NewBlocks(t, 10) const ( @@ -267,6 +266,7 @@ func TestBroadcaster_BackfillUnconsumedAfterCrash(t *testing.T) { helper := newBroadcasterHelper(t, 0, 1, logs, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].FinalityDepth = ptr[uint32](confs) }) + ctx := testutils.Context(t) orm := log.NewORM(helper.db, cltest.FixtureChainID) listener := helper.newLogListenerWithJob("one") @@ -292,6 +292,7 @@ func TestBroadcaster_BackfillUnconsumedAfterCrash(t *testing.T) { helper := newBroadcasterHelper(t, 2, 1, logs, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].FinalityDepth = ptr[uint32](confs) }) + ctx := testutils.Context(t) orm := log.NewORM(helper.db, cltest.FixtureChainID) contract1.On("ParseLog", log1).Return(flux_aggregator_wrapper.FluxAggregatorNewRound{}, nil) contract2.On("ParseLog", log2).Return(flux_aggregator_wrapper.FluxAggregatorAnswerUpdated{}, nil) @@ -318,6 +319,7 @@ func TestBroadcaster_BackfillUnconsumedAfterCrash(t *testing.T) { helper := newBroadcasterHelper(t, 4, 1, logs, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].FinalityDepth = ptr[uint32](confs) }) + ctx := testutils.Context(t) orm := log.NewORM(helper.db, cltest.FixtureChainID) listener := helper.newLogListenerWithJob("one") @@ -342,6 +344,7 @@ func TestBroadcaster_BackfillUnconsumedAfterCrash(t *testing.T) { helper := newBroadcasterHelper(t, 7, 1, logs[1:], func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].FinalityDepth = ptr[uint32](confs) }) + ctx := testutils.Context(t) orm := log.NewORM(helper.db, cltest.FixtureChainID) listener := helper.newLogListenerWithJob("one") listener2 := helper.newLogListenerWithJob("two") @@ -377,8 +380,9 @@ func (helper *broadcasterHelper) simulateHeads(t *testing.T, listener, listener2 <-headsDone + ctx := testutils.Context(t) require.Eventually(t, func() bool { - blockNum, err := orm.GetPendingMinBlock(testutils.Context(t)) + blockNum, err := orm.GetPendingMinBlock(ctx) if !assert.NoError(t, err) { return false } diff --git a/core/chains/evm/logpoller/observability.go b/core/chains/evm/logpoller/observability.go index 07a0f58ce78..14dec5274ad 100644 --- a/core/chains/evm/logpoller/observability.go +++ b/core/chains/evm/logpoller/observability.go @@ -76,9 +76,9 @@ type ObservedORM struct { // NewObservedORM creates an observed version of log poller's ORM created by NewORM // Please see ObservedLogPoller for more details on how latencies are measured -func NewObservedORM(chainID *big.Int, db sqlutil.DataSource, lggr logger.Logger) *ObservedORM { +func NewObservedORM(chainID *big.Int, ds sqlutil.DataSource, lggr logger.Logger) *ObservedORM { return &ObservedORM{ - ORM: NewORM(chainID, db, lggr), + ORM: NewORM(chainID, ds, lggr), queryDuration: lpQueryDuration, datasetSize: lpQueryDataSets, logsInserted: lpLogsInserted, diff --git a/core/chains/evm/logpoller/orm.go b/core/chains/evm/logpoller/orm.go index ebba3cffc08..838a38c8ebb 100644 --- a/core/chains/evm/logpoller/orm.go +++ b/core/chains/evm/logpoller/orm.go @@ -59,32 +59,32 @@ type ORM interface { SelectLogsDataWordBetween(ctx context.Context, address common.Address, eventSig common.Hash, wordIndexMin int, wordIndexMax int, wordValue common.Hash, confs Confirmations) ([]Log, error) } -type DbORM struct { +type DSORM struct { chainID *big.Int - db sqlutil.DataSource + ds sqlutil.DataSource lggr logger.Logger } -var _ ORM = &DbORM{} +var _ ORM = &DSORM{} -// NewORM creates an DbORM scoped to chainID. -func NewORM(chainID *big.Int, db sqlutil.DataSource, lggr logger.Logger) *DbORM { - return &DbORM{ +// NewORM creates an DSORM scoped to chainID. +func NewORM(chainID *big.Int, ds sqlutil.DataSource, lggr logger.Logger) *DSORM { + return &DSORM{ chainID: chainID, - db: db, + ds: ds, lggr: lggr, } } -func (o *DbORM) Transaction(ctx context.Context, fn func(*DbORM) error) (err error) { - return sqlutil.Transact(ctx, o.new, o.db, nil, fn) +func (o *DSORM) Transact(ctx context.Context, fn func(*DSORM) error) (err error) { + return sqlutil.Transact(ctx, o.new, o.ds, nil, fn) } -// new returns a NewORM like o, but backed by q. -func (o *DbORM) new(q sqlutil.DataSource) *DbORM { return NewORM(o.chainID, q, o.lggr) } +// new returns a NewORM like o, but backed by ds. +func (o *DSORM) new(ds sqlutil.DataSource) *DSORM { return NewORM(o.chainID, ds, o.lggr) } // InsertBlock is idempotent to support replays. -func (o *DbORM) InsertBlock(ctx context.Context, blockHash common.Hash, blockNumber int64, blockTimestamp time.Time, finalizedBlock int64) error { +func (o *DSORM) InsertBlock(ctx context.Context, blockHash common.Hash, blockNumber int64, blockTimestamp time.Time, finalizedBlock int64) error { args, err := newQueryArgs(o.chainID). withCustomHashArg("block_hash", blockHash). withCustomArg("block_number", blockNumber). @@ -98,12 +98,7 @@ func (o *DbORM) InsertBlock(ctx context.Context, blockHash common.Hash, blockNum (evm_chain_id, block_hash, block_number, block_timestamp, finalized_block_number, created_at) VALUES (:evm_chain_id, :block_hash, :block_number, :block_timestamp, :finalized_block_number, NOW()) ON CONFLICT DO NOTHING` - query, sqlArgs, err := o.db.BindNamed(query, args) - if err != nil { - return err - } - - _, err = o.db.ExecContext(ctx, query, sqlArgs...) + _, err = o.ds.NamedExecContext(ctx, query, args) return err } @@ -111,7 +106,7 @@ func (o *DbORM) InsertBlock(ctx context.Context, blockHash common.Hash, blockNum // // Each address/event pair must have a unique job id, so it may be removed when the job is deleted. // If a second job tries to overwrite the same pair, this should fail. -func (o *DbORM) InsertFilter(ctx context.Context, filter Filter) (err error) { +func (o *DSORM) InsertFilter(ctx context.Context, filter Filter) (err error) { topicArrays := []types.HashArray{filter.Topic2, filter.Topic3, filter.Topic4} args, err := newQueryArgs(o.chainID). withCustomArg("name", filter.Name). @@ -148,18 +143,13 @@ func (o *DbORM) InsertFilter(ctx context.Context, filter Filter) (err error) { topicsColumns.String(), topicsSql.String()) - query, sqlArgs, err := o.db.BindNamed(query, args) - if err != nil { - return err - } - - _, err = o.db.ExecContext(ctx, query, sqlArgs...) + _, err = o.ds.NamedExecContext(ctx, query, args) return err } // DeleteFilter removes all events,address pairs associated with the Filter -func (o *DbORM) DeleteFilter(ctx context.Context, name string) error { - _, err := o.db.ExecContext(ctx, +func (o *DSORM) DeleteFilter(ctx context.Context, name string) error { + _, err := o.ds.ExecContext(ctx, `DELETE FROM evm.log_poller_filters WHERE name = $1 AND evm_chain_id = $2`, name, ubig.New(o.chainID)) return err @@ -167,7 +157,7 @@ func (o *DbORM) DeleteFilter(ctx context.Context, name string) error { } // LoadFilters returns all filters for this chain -func (o *DbORM) LoadFilters(ctx context.Context) (map[string]Filter, error) { +func (o *DSORM) LoadFilters(ctx context.Context) (map[string]Filter, error) { query := `SELECT name, ARRAY_AGG(DISTINCT address)::BYTEA[] AS addresses, ARRAY_AGG(DISTINCT event)::BYTEA[] AS event_sigs, @@ -180,7 +170,7 @@ func (o *DbORM) LoadFilters(ctx context.Context) (map[string]Filter, error) { FROM evm.log_poller_filters WHERE evm_chain_id = $1 GROUP BY name` var rows []Filter - err := o.db.SelectContext(ctx, &rows, query, ubig.New(o.chainID)) + err := o.ds.SelectContext(ctx, &rows, query, ubig.New(o.chainID)) filters := make(map[string]Filter) for _, filter := range rows { filters[filter.Name] = filter @@ -188,31 +178,31 @@ func (o *DbORM) LoadFilters(ctx context.Context) (map[string]Filter, error) { return filters, err } -func (o *DbORM) SelectBlockByHash(ctx context.Context, hash common.Hash) (*LogPollerBlock, error) { +func (o *DSORM) SelectBlockByHash(ctx context.Context, hash common.Hash) (*LogPollerBlock, error) { var b LogPollerBlock - if err := o.db.GetContext(ctx, &b, `SELECT * FROM evm.log_poller_blocks WHERE block_hash = $1 AND evm_chain_id = $2`, hash.Bytes(), ubig.New(o.chainID)); err != nil { + if err := o.ds.GetContext(ctx, &b, `SELECT * FROM evm.log_poller_blocks WHERE block_hash = $1 AND evm_chain_id = $2`, hash.Bytes(), ubig.New(o.chainID)); err != nil { return nil, err } return &b, nil } -func (o *DbORM) SelectBlockByNumber(ctx context.Context, n int64) (*LogPollerBlock, error) { +func (o *DSORM) SelectBlockByNumber(ctx context.Context, n int64) (*LogPollerBlock, error) { var b LogPollerBlock - if err := o.db.GetContext(ctx, &b, `SELECT * FROM evm.log_poller_blocks WHERE block_number = $1 AND evm_chain_id = $2`, n, ubig.New(o.chainID)); err != nil { + if err := o.ds.GetContext(ctx, &b, `SELECT * FROM evm.log_poller_blocks WHERE block_number = $1 AND evm_chain_id = $2`, n, ubig.New(o.chainID)); err != nil { return nil, err } return &b, nil } -func (o *DbORM) SelectLatestBlock(ctx context.Context) (*LogPollerBlock, error) { +func (o *DSORM) SelectLatestBlock(ctx context.Context) (*LogPollerBlock, error) { var b LogPollerBlock - if err := o.db.GetContext(ctx, &b, `SELECT * FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1`, ubig.New(o.chainID)); err != nil { + if err := o.ds.GetContext(ctx, &b, `SELECT * FROM evm.log_poller_blocks WHERE evm_chain_id = $1 ORDER BY block_number DESC LIMIT 1`, ubig.New(o.chainID)); err != nil { return nil, err } return &b, nil } -func (o *DbORM) SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs Confirmations) (*Log, error) { +func (o *DSORM) SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs Confirmations) (*Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withConfs(confs). toArgs() @@ -228,11 +218,11 @@ func (o *DbORM) SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig ORDER BY (block_number, log_index) DESC LIMIT 1`, nestedBlockNumberQuery(confs)) var l Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err = o.db.GetContext(ctx, &l, query, sqlArgs...); err != nil { + if err = o.ds.GetContext(ctx, &l, query, sqlArgs...); err != nil { return nil, err } return &l, nil @@ -240,9 +230,9 @@ func (o *DbORM) SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig // DeleteBlocksBefore delete blocks before and including end. When limit is set, it will delete at most limit blocks. // Otherwise, it will delete all blocks at once. -func (o *DbORM) DeleteBlocksBefore(ctx context.Context, end int64, limit int64) (int64, error) { +func (o *DSORM) DeleteBlocksBefore(ctx context.Context, end int64, limit int64) (int64, error) { if limit > 0 { - result, err := o.db.ExecContext(ctx, + result, err := o.ds.ExecContext(ctx, `DELETE FROM evm.log_poller_blocks WHERE block_number IN ( SELECT block_number FROM evm.log_poller_blocks @@ -257,7 +247,7 @@ func (o *DbORM) DeleteBlocksBefore(ctx context.Context, end int64, limit int64) } return result.RowsAffected() } - result, err := o.db.ExecContext(ctx, `DELETE FROM evm.log_poller_blocks + result, err := o.ds.ExecContext(ctx, `DELETE FROM evm.log_poller_blocks WHERE block_number <= $1 AND evm_chain_id = $2`, end, ubig.New(o.chainID)) if err != nil { return 0, err @@ -265,16 +255,16 @@ func (o *DbORM) DeleteBlocksBefore(ctx context.Context, end int64, limit int64) return result.RowsAffected() } -func (o *DbORM) DeleteLogsAndBlocksAfter(ctx context.Context, start int64) error { +func (o *DSORM) DeleteLogsAndBlocksAfter(ctx context.Context, start int64) error { // These deletes are bounded by reorg depth, so they are // fast and should not slow down the log readers. - return o.Transaction(ctx, func(orm *DbORM) error { + return o.Transact(ctx, func(orm *DSORM) error { // Applying upper bound filter is critical for Postgres performance (especially for evm.logs table) // because it allows the planner to properly estimate the number of rows to be scanned. // If not applied, these queries can become very slow. After some critical number // of logs, Postgres will try to scan all the logs in the index by block_number. // Latency without upper bound filter can be orders of magnitude higher for large number of logs. - _, err := o.db.ExecContext(ctx, `DELETE FROM evm.log_poller_blocks + _, err := o.ds.ExecContext(ctx, `DELETE FROM evm.log_poller_blocks WHERE evm_chain_id = $1 AND block_number >= $2 AND block_number <= (SELECT MAX(block_number) @@ -286,7 +276,7 @@ func (o *DbORM) DeleteLogsAndBlocksAfter(ctx context.Context, start int64) error return err } - _, err = o.db.ExecContext(ctx, `DELETE FROM evm.logs + _, err = o.ds.ExecContext(ctx, `DELETE FROM evm.logs WHERE evm_chain_id = $1 AND block_number >= $2 AND block_number <= (SELECT MAX(block_number) FROM evm.logs WHERE evm_chain_id = $1)`, @@ -307,11 +297,11 @@ type Exp struct { ShouldDelete bool } -func (o *DbORM) DeleteExpiredLogs(ctx context.Context, limit int64) (int64, error) { +func (o *DSORM) DeleteExpiredLogs(ctx context.Context, limit int64) (int64, error) { var err error var result sql.Result if limit > 0 { - result, err = o.db.ExecContext(ctx, ` + result, err = o.ds.ExecContext(ctx, ` DELETE FROM evm.logs WHERE (evm_chain_id, address, event_sig, block_number) IN ( SELECT l.evm_chain_id, l.address, l.event_sig, l.block_number @@ -327,7 +317,7 @@ func (o *DbORM) DeleteExpiredLogs(ctx context.Context, limit int64) (int64, erro LIMIT $2 )`, ubig.New(o.chainID), limit) } else { - result, err = o.db.ExecContext(ctx, `WITH r AS + result, err = o.ds.ExecContext(ctx, `WITH r AS ( SELECT address, event, MAX(retention) AS retention FROM evm.log_poller_filters WHERE evm_chain_id=$1 GROUP BY evm_chain_id,address, event HAVING NOT 0 = ANY(ARRAY_AGG(retention)) @@ -344,16 +334,16 @@ func (o *DbORM) DeleteExpiredLogs(ctx context.Context, limit int64) (int64, erro } // InsertLogs is idempotent to support replays. -func (o *DbORM) InsertLogs(ctx context.Context, logs []Log) error { +func (o *DSORM) InsertLogs(ctx context.Context, logs []Log) error { if err := o.validateLogs(logs); err != nil { return err } - return o.Transaction(ctx, func(orm *DbORM) error { - return orm.insertLogsWithinTx(ctx, logs, orm.db) + return o.Transact(ctx, func(orm *DSORM) error { + return orm.insertLogsWithinTx(ctx, logs, orm.ds) }) } -func (o *DbORM) InsertLogsWithBlock(ctx context.Context, logs []Log, block LogPollerBlock) error { +func (o *DSORM) InsertLogsWithBlock(ctx context.Context, logs []Log, block LogPollerBlock) error { // Optimization, don't open TX when there is only a block to be persisted if len(logs) == 0 { return o.InsertBlock(ctx, block.BlockHash, block.BlockNumber, block.BlockTimestamp, block.FinalizedBlockNumber) @@ -364,16 +354,16 @@ func (o *DbORM) InsertLogsWithBlock(ctx context.Context, logs []Log, block LogPo } // Block and logs goes with the same TX to ensure atomicity - return o.Transaction(ctx, func(orm *DbORM) error { + return o.Transact(ctx, func(orm *DSORM) error { err := orm.InsertBlock(ctx, block.BlockHash, block.BlockNumber, block.BlockTimestamp, block.FinalizedBlockNumber) if err != nil { return err } - return orm.insertLogsWithinTx(ctx, logs, orm.db) + return orm.insertLogsWithinTx(ctx, logs, orm.ds) }) } -func (o *DbORM) insertLogsWithinTx(ctx context.Context, logs []Log, tx sqlutil.DataSource) error { +func (o *DSORM) insertLogsWithinTx(ctx context.Context, logs []Log, tx sqlutil.DataSource) error { batchInsertSize := 4000 for i := 0; i < len(logs); i += batchInsertSize { start, end := i, i+batchInsertSize @@ -387,12 +377,10 @@ func (o *DbORM) insertLogsWithinTx(ctx context.Context, logs []Log, tx sqlutil.D (:evm_chain_id, :log_index, :block_hash, :block_number, :block_timestamp, :address, :event_sig, :topics, :tx_hash, :data, NOW()) ON CONFLICT DO NOTHING` - query, sqlArgs, err := o.db.BindNamed(query, logs[start:end]) + _, err := o.ds.NamedExecContext(ctx, query, logs[start:end]) if err != nil { return err } - - _, err = tx.ExecContext(ctx, query, sqlArgs...) if err != nil { if pkgerrors.Is(err, context.DeadlineExceeded) && batchInsertSize > 500 { // In case of DB timeouts, try to insert again with a smaller batch upto a limit @@ -406,7 +394,7 @@ func (o *DbORM) insertLogsWithinTx(ctx context.Context, logs []Log, tx sqlutil.D return nil } -func (o *DbORM) validateLogs(logs []Log) error { +func (o *DSORM) validateLogs(logs []Log) error { for _, log := range logs { if o.chainID.Cmp(log.EvmChainId.ToInt()) != 0 { return pkgerrors.Errorf("invalid chainID in log got %v want %v", log.EvmChainId.ToInt(), o.chainID) @@ -415,7 +403,7 @@ func (o *DbORM) validateLogs(logs []Log) error { return nil } -func (o *DbORM) SelectLogsByBlockRange(ctx context.Context, start, end int64) ([]Log, error) { +func (o *DSORM) SelectLogsByBlockRange(ctx context.Context, start, end int64) ([]Log, error) { args, err := newQueryArgs(o.chainID). withStartBlock(start). withEndBlock(end). @@ -431,12 +419,12 @@ func (o *DbORM) SelectLogsByBlockRange(ctx context.Context, start, end int64) ([ ORDER BY (block_number, log_index)` var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - err = o.db.SelectContext(ctx, &logs, query, sqlArgs...) + err = o.ds.SelectContext(ctx, &logs, query, sqlArgs...) if err != nil { return nil, err } @@ -444,7 +432,7 @@ func (o *DbORM) SelectLogsByBlockRange(ctx context.Context, start, end int64) ([ } // SelectLogs finds the logs in a given block range. -func (o *DbORM) SelectLogs(ctx context.Context, start, end int64, address common.Address, eventSig common.Hash) ([]Log, error) { +func (o *DSORM) SelectLogs(ctx context.Context, start, end int64, address common.Address, eventSig common.Hash) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withStartBlock(start). withEndBlock(end). @@ -462,12 +450,12 @@ func (o *DbORM) SelectLogs(ctx context.Context, start, end int64, address common ORDER BY (block_number, log_index)` var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - err = o.db.SelectContext(ctx, &logs, query, sqlArgs...) + err = o.ds.SelectContext(ctx, &logs, query, sqlArgs...) if err != nil { return nil, err } @@ -475,7 +463,7 @@ func (o *DbORM) SelectLogs(ctx context.Context, start, end int64, address common } // SelectLogsCreatedAfter finds logs created after some timestamp. -func (o *DbORM) SelectLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, after time.Time, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, after time.Time, confs Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withBlockTimestampAfter(after). withConfs(confs). @@ -494,12 +482,12 @@ func (o *DbORM) SelectLogsCreatedAfter(ctx context.Context, address common.Addre ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err = o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err = o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, err } return logs, nil @@ -507,7 +495,7 @@ func (o *DbORM) SelectLogsCreatedAfter(ctx context.Context, address common.Addre // SelectLogsWithSigs finds the logs in the given block range with the given event signatures // emitted from the given address. -func (o *DbORM) SelectLogsWithSigs(ctx context.Context, start, end int64, address common.Address, eventSigs []common.Hash) (logs []Log, err error) { +func (o *DSORM) SelectLogsWithSigs(ctx context.Context, start, end int64, address common.Address, eventSigs []common.Hash) (logs []Log, err error) { args, err := newQueryArgs(o.chainID). withAddress(address). withEventSigArray(eventSigs). @@ -525,19 +513,19 @@ func (o *DbORM) SelectLogsWithSigs(ctx context.Context, start, end int64, addres AND block_number BETWEEN :start_block AND :end_block ORDER BY (block_number, log_index)` - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - err = o.db.SelectContext(ctx, &logs, query, sqlArgs...) + err = o.ds.SelectContext(ctx, &logs, query, sqlArgs...) if pkgerrors.Is(err, sql.ErrNoRows) { return nil, nil } return logs, err } -func (o *DbORM) GetBlocksRange(ctx context.Context, start int64, end int64) ([]LogPollerBlock, error) { +func (o *DSORM) GetBlocksRange(ctx context.Context, start int64, end int64) ([]LogPollerBlock, error) { args, err := newQueryArgs(o.chainID). withStartBlock(start). withEndBlock(end). @@ -553,12 +541,12 @@ func (o *DbORM) GetBlocksRange(ctx context.Context, start int64, end int64) ([]L ORDER BY block_number ASC` var blocks []LogPollerBlock - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - err = o.db.SelectContext(ctx, &blocks, query, sqlArgs...) + err = o.ds.SelectContext(ctx, &blocks, query, sqlArgs...) if err != nil { return nil, err } @@ -566,7 +554,7 @@ func (o *DbORM) GetBlocksRange(ctx context.Context, start int64, end int64) ([]L } // SelectLatestLogEventSigsAddrsWithConfs finds the latest log by (address, event) combination that matches a list of Addresses and list of events -func (o *DbORM) SelectLatestLogEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, addresses []common.Address, eventSigs []common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectLatestLogEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, addresses []common.Address, eventSigs []common.Hash, confs Confirmations) ([]Log, error) { args, err := newQueryArgs(o.chainID). withAddressArray(addresses). withEventSigArray(eventSigs). @@ -590,19 +578,19 @@ func (o *DbORM) SelectLatestLogEventSigsAddrsWithConfs(ctx context.Context, from ORDER BY block_number ASC`, nestedBlockNumberQuery(confs)) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err = o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err = o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, pkgerrors.Wrap(err, "failed to execute query") } return logs, nil } // SelectLatestBlockByEventSigsAddrsWithConfs finds the latest block number that matches a list of Addresses and list of events. It returns 0 if there is no matching block -func (o *DbORM) SelectLatestBlockByEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs Confirmations) (int64, error) { +func (o *DSORM) SelectLatestBlockByEventSigsAddrsWithConfs(ctx context.Context, fromBlock int64, eventSigs []common.Hash, addresses []common.Address, confs Confirmations) (int64, error) { args, err := newQueryArgs(o.chainID). withEventSigArray(eventSigs). withAddressArray(addresses). @@ -621,18 +609,18 @@ func (o *DbORM) SelectLatestBlockByEventSigsAddrsWithConfs(ctx context.Context, AND block_number <= %s`, nestedBlockNumberQuery(confs)) var blockNumber int64 - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return 0, err } - if err = o.db.GetContext(ctx, &blockNumber, query, sqlArgs...); err != nil { + if err = o.ds.GetContext(ctx, &blockNumber, query, sqlArgs...); err != nil { return 0, err } return blockNumber, nil } -func (o *DbORM) SelectLogsDataWordRange(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin, wordValueMax common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectLogsDataWordRange(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin, wordValueMax common.Hash, confs Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withWordIndex(wordIndex). withWordValueMin(wordValueMin). @@ -653,18 +641,18 @@ func (o *DbORM) SelectLogsDataWordRange(ctx context.Context, address common.Addr ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err := o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err := o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, err } return logs, nil } -func (o *DbORM) SelectLogsDataWordGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectLogsDataWordGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, wordIndex int, wordValueMin common.Hash, confs Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withWordIndex(wordIndex). withWordValueMin(wordValueMin). @@ -684,18 +672,18 @@ func (o *DbORM) SelectLogsDataWordGreaterThan(ctx context.Context, address commo ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err := o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err := o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, err } return logs, nil } -func (o *DbORM) SelectLogsDataWordBetween(ctx context.Context, address common.Address, eventSig common.Hash, wordIndexMin int, wordIndexMax int, wordValue common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectLogsDataWordBetween(ctx context.Context, address common.Address, eventSig common.Hash, wordIndexMin int, wordIndexMax int, wordValue common.Hash, confs Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withWordIndexMin(wordIndexMin). withWordIndexMax(wordIndexMax). @@ -716,18 +704,18 @@ func (o *DbORM) SelectLogsDataWordBetween(ctx context.Context, address common.Ad ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err := o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err := o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, err } return logs, nil } -func (o *DbORM) SelectIndexedLogsTopicGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectIndexedLogsTopicGreaterThan(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin common.Hash, confs Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withTopicIndex(topicIndex). withTopicValueMin(topicValueMin). @@ -747,18 +735,18 @@ func (o *DbORM) SelectIndexedLogsTopicGreaterThan(ctx context.Context, address c ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err := o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err := o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, err } return logs, nil } -func (o *DbORM) SelectIndexedLogsTopicRange(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin, topicValueMax common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectIndexedLogsTopicRange(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValueMin, topicValueMax common.Hash, confs Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withTopicIndex(topicIndex). withTopicValueMin(topicValueMin). @@ -780,18 +768,18 @@ func (o *DbORM) SelectIndexedLogsTopicRange(ctx context.Context, address common. ORDER BY (evm.logs.block_number, evm.logs.log_index)`, nestedBlockNumberQuery(confs)) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err := o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err := o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, err } return logs, nil } -func (o *DbORM) SelectIndexedLogs(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectIndexedLogs(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, confs Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withTopicIndex(topicIndex). withTopicValues(topicValues). @@ -811,19 +799,19 @@ func (o *DbORM) SelectIndexedLogs(ctx context.Context, address common.Address, e ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err := o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err := o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, err } return logs, nil } // SelectIndexedLogsByBlockRange finds the indexed logs in a given block range. -func (o *DbORM) SelectIndexedLogsByBlockRange(ctx context.Context, start, end int64, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash) ([]Log, error) { +func (o *DSORM) SelectIndexedLogsByBlockRange(ctx context.Context, start, end int64, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withTopicIndex(topicIndex). withTopicValues(topicValues). @@ -844,19 +832,19 @@ func (o *DbORM) SelectIndexedLogsByBlockRange(ctx context.Context, start, end in ORDER BY (block_number, log_index)` var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - err = o.db.SelectContext(ctx, &logs, query, sqlArgs...) + err = o.ds.SelectContext(ctx, &logs, query, sqlArgs...) if err != nil { return nil, err } return logs, nil } -func (o *DbORM) SelectIndexedLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, after time.Time, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectIndexedLogsCreatedAfter(ctx context.Context, address common.Address, eventSig common.Hash, topicIndex int, topicValues []common.Hash, after time.Time, confs Confirmations) ([]Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withBlockTimestampAfter(after). withConfs(confs). @@ -878,18 +866,18 @@ func (o *DbORM) SelectIndexedLogsCreatedAfter(ctx context.Context, address commo ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err := o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err := o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, err } return logs, nil } -func (o *DbORM) SelectIndexedLogsByTxHash(ctx context.Context, address common.Address, eventSig common.Hash, txHash common.Hash) ([]Log, error) { +func (o *DSORM) SelectIndexedLogsByTxHash(ctx context.Context, address common.Address, eventSig common.Hash, txHash common.Hash) ([]Log, error) { args, err := newQueryArgs(o.chainID). withTxHash(txHash). withAddress(address). @@ -907,12 +895,12 @@ func (o *DbORM) SelectIndexedLogsByTxHash(ctx context.Context, address common.Ad ORDER BY (block_number, log_index)` var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - err = o.db.SelectContext(ctx, &logs, query, sqlArgs...) + err = o.ds.SelectContext(ctx, &logs, query, sqlArgs...) if err != nil { return nil, err } @@ -920,7 +908,7 @@ func (o *DbORM) SelectIndexedLogsByTxHash(ctx context.Context, address common.Ad } // SelectIndexedLogsWithSigsExcluding query's for logs that have signature A and exclude logs that have a corresponding signature B, matching is done based on the topic index both logs should be inside the block range and have the minimum number of confirmations -func (o *DbORM) SelectIndexedLogsWithSigsExcluding(ctx context.Context, sigA, sigB common.Hash, topicIndex int, address common.Address, startBlock, endBlock int64, confs Confirmations) ([]Log, error) { +func (o *DSORM) SelectIndexedLogsWithSigsExcluding(ctx context.Context, sigA, sigB common.Hash, topicIndex int, address common.Address, startBlock, endBlock int64, confs Confirmations) ([]Log, error) { args, err := newQueryArgs(o.chainID). withAddress(address). withTopicIndex(topicIndex). @@ -955,12 +943,12 @@ func (o *DbORM) SelectIndexedLogsWithSigsExcluding(ctx context.Context, sigA, si ORDER BY block_number,log_index ASC`, nestedQuery, nestedQuery) var logs []Log - query, sqlArgs, err := o.db.BindNamed(query, args) + query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { return nil, err } - if err := o.db.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { + if err := o.ds.SelectContext(ctx, &logs, query, sqlArgs...); err != nil { return nil, err } return logs, nil diff --git a/core/chains/evm/logpoller/query.go b/core/chains/evm/logpoller/query.go index 6aabe59045d..f9d2c45bce1 100644 --- a/core/chains/evm/logpoller/query.go +++ b/core/chains/evm/logpoller/query.go @@ -24,7 +24,7 @@ func concatBytes[T bytesProducer](byteSlice []T) [][]byte { return output } -// queryArgs is a helper for building the arguments to a postgres query created by DbORM +// queryArgs is a helper for building the arguments to a postgres query created by DSORM // Besides the convenience methods, it also keeps track of arguments validation and sanitization. type queryArgs struct { args map[string]interface{} diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go index 4e19a2ec7da..20c069a46d6 100644 --- a/core/chains/evm/txmgr/broadcaster_test.go +++ b/core/chains/evm/txmgr/broadcaster_test.go @@ -1112,7 +1112,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { } t.Run("with erroring callback bails out", func(t *testing.T) { - require.NoError(t, txStore.InsertTx(ctx, &etx)) + require.NoError(t, txStore.InsertTx(testutils.Context(t), &etx)) fn := func(ctx context.Context, id uuid.UUID, result interface{}, err error) error { return errors.New("something exploded in the callback") } diff --git a/core/chains/evm/txmgr/builder.go b/core/chains/evm/txmgr/builder.go index f13efb2b258..0671f49bb74 100644 --- a/core/chains/evm/txmgr/builder.go +++ b/core/chains/evm/txmgr/builder.go @@ -4,8 +4,6 @@ import ( "math/big" "time" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/common/txmgr" @@ -21,8 +19,7 @@ import ( // NewTxm constructs the necessary dependencies for the EvmTxm (broadcaster, confirmer, etc) and returns a new EvmTxManager func NewTxm( - sqlxDB *sqlx.DB, - db sqlutil.DataSource, + ds sqlutil.DataSource, chainConfig ChainConfig, fCfg FeeConfig, txConfig config.Transactions, @@ -40,14 +37,14 @@ func NewTxm( var fwdMgr FwdMgr if txConfig.ForwardersEnabled() { - fwdMgr = forwarders.NewFwdMgr(db, client, logPoller, lggr, chainConfig) + fwdMgr = forwarders.NewFwdMgr(ds, client, logPoller, lggr, chainConfig) } else { lggr.Info("EvmForwarderManager: Disabled") } checker := &CheckerFactory{Client: client} // create tx attempt builder txAttemptBuilder := NewEvmTxAttemptBuilder(*client.ConfiguredChainID(), fCfg, keyStore, estimator) - txStore := NewTxStore(sqlxDB, lggr) + txStore := NewTxStore(ds, lggr) txmCfg := NewEvmTxmConfig(chainConfig) // wrap Evm specific config feeCfg := NewEvmTxmFeeConfig(fCfg) // wrap Evm specific config txmClient := NewEvmTxmClient(client, clientErrors) // wrap Evm specific client diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index c8e664e8cfe..dedba07b594 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -115,7 +115,7 @@ func DbReceiptToEvmReceipt(receipt *dbReceipt) *evmtypes.Receipt { // Directly maps to onchain receipt schema. type rawOnchainReceipt = evmtypes.Receipt -func (o *evmTxStore) Transaction(ctx context.Context, readOnly bool, fn func(*evmTxStore) error) (err error) { +func (o *evmTxStore) Transact(ctx context.Context, readOnly bool, fn func(*evmTxStore) error) (err error) { opts := &sqlutil.TxOptions{TxOptions: sql.TxOptions{ReadOnly: readOnly}} return sqlutil.Transact(ctx, o.new, o.q, opts, fn) } @@ -509,7 +509,7 @@ func (o *evmTxStore) FindTxAttemptsByTxIDs(ctx context.Context, ids []int64) ([] func (o *evmTxStore) FindTxByHash(ctx context.Context, hash common.Hash) (*Tx, error) { var dbEtx DbEthTx - err := o.Transaction(ctx, true, func(orm *evmTxStore) error { + err := o.Transact(ctx, true, func(orm *evmTxStore) error { sql := `SELECT evm.txes.* FROM evm.txes WHERE id IN (SELECT DISTINCT eth_tx_id FROM evm.tx_attempts WHERE hash = $1)` if err := orm.q.GetContext(ctx, &dbEtx, sql, hash); err != nil { return pkgerrors.Wrapf(err, "failed to find eth_tx with hash %d", hash) @@ -575,7 +575,7 @@ func (o *evmTxStore) GetFatalTransactions(ctx context.Context) (txes []*Tx, err var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { stmt := `SELECT * FROM evm.txes WHERE state = 'fatal_error'` var dbEtxs []DbEthTx if err = orm.q.SelectContext(ctx, &dbEtxs, stmt); err != nil { @@ -595,7 +595,7 @@ func (o *evmTxStore) GetFatalTransactions(ctx context.Context) (txes []*Tx, err // FindTxWithAttempts finds the Tx with its attempts and receipts preloaded func (o *evmTxStore) FindTxWithAttempts(ctx context.Context, etxID int64) (etx Tx, err error) { - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { var dbEtx DbEthTx if err = orm.q.GetContext(ctx, &dbEtx, `SELECT * FROM evm.txes WHERE id = $1 ORDER BY created_at ASC, id ASC`, etxID); err != nil { return pkgerrors.Wrapf(err, "failed to find evm.tx with id %d", etxID) @@ -614,7 +614,7 @@ func (o *evmTxStore) FindTxWithAttempts(ctx context.Context, etxID int64) (etx T func (o *evmTxStore) FindTxAttemptConfirmedByTxIDs(ctx context.Context, ids []int64) ([]TxAttempt, error) { var txAttempts []TxAttempt - err := o.Transaction(ctx, true, func(orm *evmTxStore) error { + err := o.Transact(ctx, true, func(orm *evmTxStore) error { var dbAttempts []DbEthTxAttempt if err := orm.q.SelectContext(ctx, &dbAttempts, `SELECT eta.* FROM evm.tx_attempts eta @@ -806,7 +806,7 @@ func (o *evmTxStore) FindTxAttemptsRequiringReceiptFetch(ctx context.Context, ch var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { var dbAttempts []DbEthTxAttempt err = orm.q.SelectContext(ctx, &dbAttempts, ` SELECT evm.tx_attempts.* FROM evm.tx_attempts @@ -963,7 +963,7 @@ func (o *evmTxStore) GetInProgressTxAttempts(ctx context.Context, address common var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { var dbAttempts []DbEthTxAttempt err = orm.q.SelectContext(ctx, &dbAttempts, ` SELECT evm.tx_attempts.* FROM evm.tx_attempts @@ -1046,7 +1046,7 @@ func (o *evmTxStore) FindTxWithSequence(ctx context.Context, fromAddress common. ctx, cancel = o.mergeContexts(ctx) defer cancel() etx = new(Tx) - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { var dbEtx DbEthTx err = orm.q.GetContext(ctx, &dbEtx, ` SELECT * FROM evm.txes WHERE from_address = $1 AND nonce = $2 AND state IN ('confirmed', 'confirmed_missing_receipt', 'unconfirmed') @@ -1094,7 +1094,7 @@ func (o *evmTxStore) UpdateTxForRebroadcast(ctx context.Context, etx Tx, etxAtte var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - return o.Transaction(ctx, false, func(orm *evmTxStore) error { + return o.Transact(ctx, false, func(orm *evmTxStore) error { if err := deleteEthReceipts(ctx, orm, etx.ID); err != nil { return pkgerrors.Wrapf(err, "deleteEthReceipts failed for etx %v", etx.ID) } @@ -1109,7 +1109,7 @@ func (o *evmTxStore) FindTransactionsConfirmedInBlockRange(ctx context.Context, var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { var dbEtxs []DbEthTx err = orm.q.SelectContext(ctx, &dbEtxs, ` SELECT DISTINCT evm.txes.* FROM evm.txes @@ -1136,7 +1136,7 @@ func (o *evmTxStore) FindEarliestUnconfirmedBroadcastTime(ctx context.Context, c var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { if err = orm.q.QueryRowxContext(ctx, `SELECT min(initial_broadcast_at) FROM evm.txes WHERE state = 'unconfirmed' AND evm_chain_id = $1`, chainID.String()).Scan(&broadcastAt); err != nil { return fmt.Errorf("failed to query for unconfirmed eth_tx count: %w", err) } @@ -1149,7 +1149,7 @@ func (o *evmTxStore) FindEarliestUnconfirmedTxAttemptBlock(ctx context.Context, var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { err = orm.q.QueryRowxContext(ctx, ` SELECT MIN(broadcast_before_block_num) FROM evm.tx_attempts JOIN evm.txes ON evm.txes.id = evm.tx_attempts.eth_tx_id @@ -1184,7 +1184,7 @@ func (o *evmTxStore) IsTxFinalized(ctx context.Context, blockHeight int64, txID func (o *evmTxStore) saveAttemptWithNewState(ctx context.Context, attempt TxAttempt, broadcastAt time.Time) error { var dbAttempt DbEthTxAttempt dbAttempt.FromTxAttempt(&attempt) - return o.Transaction(ctx, false, func(orm *evmTxStore) error { + return o.Transact(ctx, false, func(orm *evmTxStore) error { // In case of null broadcast_at (shouldn't happen) we don't want to // update anyway because it indicates a state where broadcast_at makes // no sense e.g. fatal_error @@ -1230,7 +1230,7 @@ func (o *evmTxStore) SaveConfirmedMissingReceiptAttempt(ctx context.Context, tim var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err := o.Transaction(ctx, false, func(orm *evmTxStore) error { + err := o.Transact(ctx, false, func(orm *evmTxStore) error { if err := orm.saveSentAttempt(ctx, timeout, attempt, broadcastAt); err != nil { return err } @@ -1321,7 +1321,7 @@ func (o *evmTxStore) GetTxByID(ctx context.Context, id int64) (txe *Tx, err erro ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { stmt := `SELECT * FROM evm.txes WHERE id = $1` var dbEtxs []DbEthTx if err = orm.q.SelectContext(ctx, &dbEtxs, stmt, id); err != nil { @@ -1355,7 +1355,7 @@ func (o *evmTxStore) FindTxsRequiringGasBump(ctx context.Context, address common var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { stmt := ` SELECT evm.txes.* FROM evm.txes LEFT JOIN evm.tx_attempts ON evm.txes.id = evm.tx_attempts.eth_tx_id AND (broadcast_before_block_num > $4 OR broadcast_before_block_num IS NULL OR evm.tx_attempts.state != 'broadcast') @@ -1382,7 +1382,7 @@ func (o *evmTxStore) FindTxsRequiringResubmissionDueToInsufficientFunds(ctx cont var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { var dbEtxs []DbEthTx err = orm.q.SelectContext(ctx, &dbEtxs, ` SELECT DISTINCT evm.txes.* FROM evm.txes @@ -1423,7 +1423,7 @@ func (o *evmTxStore) MarkOldTxesMissingReceiptAsErrored(ctx context.Context, blo return nil } // note: if QOpt passes in a sql.Tx this will reuse it - return o.Transaction(ctx, false, func(orm *evmTxStore) error { + return o.Transact(ctx, false, func(orm *evmTxStore) error { type etx struct { ID int64 Nonce int64 @@ -1511,7 +1511,7 @@ func (o *evmTxStore) SaveReplacementInProgressAttempt(ctx context.Context, oldAt if oldAttempt.ID == 0 { return errors.New("expected oldAttempt to have an ID") } - return o.Transaction(ctx, false, func(orm *evmTxStore) error { + return o.Transact(ctx, false, func(orm *evmTxStore) error { if _, err := orm.q.ExecContext(ctx, `DELETE FROM evm.tx_attempts WHERE id=$1`, oldAttempt.ID); err != nil { return pkgerrors.Wrap(err, "saveReplacementInProgressAttempt failed to delete from evm.tx_attempts") } @@ -1557,7 +1557,7 @@ func (o *evmTxStore) UpdateTxFatalError(ctx context.Context, etx *Tx) error { etx.Sequence = nil etx.State = txmgr.TxFatalError - return o.Transaction(ctx, false, func(orm *evmTxStore) error { + return o.Transact(ctx, false, func(orm *evmTxStore) error { if _, err := orm.q.ExecContext(ctx, `DELETE FROM evm.tx_attempts WHERE eth_tx_id = $1`, etx.ID); err != nil { return pkgerrors.Wrapf(err, "saveFatallyErroredTransaction failed to delete eth_tx_attempt with eth_tx.ID %v", etx.ID) } @@ -1591,7 +1591,7 @@ func (o *evmTxStore) UpdateTxAttemptInProgressToBroadcast(ctx context.Context, e } etx.State = txmgr.TxUnconfirmed attempt.State = NewAttemptState - return o.Transaction(ctx, false, func(orm *evmTxStore) error { + return o.Transact(ctx, false, func(orm *evmTxStore) error { var dbEtx DbEthTx dbEtx.FromTx(etx) if err := orm.q.GetContext(ctx, &dbEtx, `UPDATE evm.txes SET state=$1, error=$2, broadcast_at=$3, initial_broadcast_at=$4 WHERE id = $5 RETURNING *`, dbEtx.State, dbEtx.Error, dbEtx.BroadcastAt, dbEtx.InitialBroadcastAt, dbEtx.ID); err != nil { @@ -1622,7 +1622,7 @@ func (o *evmTxStore) UpdateTxUnstartedToInProgress(ctx context.Context, etx *Tx, return errors.New("attempt state must be in_progress") } etx.State = txmgr.TxInProgress - return o.Transaction(ctx, false, func(orm *evmTxStore) error { + return o.Transact(ctx, false, func(orm *evmTxStore) error { // If a replay was triggered while unconfirmed transactions were pending, they will be marked as fatal_error => abandoned. // In this case, we must remove the abandoned attempt from evm.tx_attempts before replacing it with a new one. In any other // case, we uphold the constraint, leaving the original tx attempt as-is and returning the constraint violation error. @@ -1688,7 +1688,7 @@ func (o *evmTxStore) GetTxInProgress(ctx context.Context, fromAddress common.Add if err != nil { return etx, pkgerrors.Wrap(err, "getInProgressEthTx failed") } - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { var dbEtx DbEthTx err = orm.q.GetContext(ctx, &dbEtx, `SELECT * FROM evm.txes WHERE from_address = $1 and state = 'in_progress'`, fromAddress) if errors.Is(err, sql.ErrNoRows) { @@ -1776,7 +1776,7 @@ func (o *evmTxStore) CreateTransaction(ctx context.Context, txRequest TxRequest, ctx, cancel = o.mergeContexts(ctx) defer cancel() var dbEtx DbEthTx - err = o.Transaction(ctx, false, func(orm *evmTxStore) error { + err = o.Transact(ctx, false, func(orm *evmTxStore) error { if txRequest.PipelineTaskRunID != nil { err = orm.q.GetContext(ctx, &dbEtx, `SELECT * FROM evm.txes WHERE pipeline_task_run_id = $1 AND evm_chain_id = $2`, txRequest.PipelineTaskRunID, chainID.String()) @@ -1810,7 +1810,7 @@ func (o *evmTxStore) PruneUnstartedTxQueue(ctx context.Context, queueSize uint32 var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, false, func(orm *evmTxStore) error { + err = o.Transact(ctx, false, func(orm *evmTxStore) error { err := orm.q.SelectContext(ctx, &ids, ` DELETE FROM evm.txes WHERE state = 'unstarted' AND subject = $1 AND @@ -1945,7 +1945,7 @@ func (o *evmTxStore) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Co var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { + err = o.Transact(ctx, true, func(orm *evmTxStore) error { var dbEtxs []DbEthTx if err = orm.q.SelectContext(ctx, &dbEtxs, `SELECT * FROM evm.txes WHERE id = ANY($1) AND state = ANY($2) AND evm_chain_id = $3`, pq.Array(ids), pq.Array(states), chainID.String()); err != nil { return pkgerrors.Wrapf(err, "failed to find evm.txes") diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go index aac9d89c490..85d25d8a70b 100644 --- a/core/chains/evm/txmgr/txmgr_test.go +++ b/core/chains/evm/txmgr/txmgr_test.go @@ -68,7 +68,6 @@ func makeTestEvmTxm( ) return txmgr.NewTxm( - db, db, ccfg, fcfg, diff --git a/core/chains/legacyevm/chain.go b/core/chains/legacyevm/chain.go index 920532518ab..27e0155da52 100644 --- a/core/chains/legacyevm/chain.go +++ b/core/chains/legacyevm/chain.go @@ -9,8 +9,6 @@ import ( gotoml "github.com/pelletier/go-toml/v2" "go.uber.org/multierr" - "github.com/jmoiron/sqlx" - common "github.com/smartcontractkit/chainlink-common/pkg/chains" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" @@ -162,8 +160,7 @@ type ChainOpts struct { MailMon *mailbox.Monitor GasEstimator gas.EvmFeeEstimator - SqlxDB *sqlx.DB // Deprecated: use DB instead - DB sqlutil.DataSource + DS sqlutil.DataSource // TODO BCF-2513 remove test code from the API // Gen-functions are useful for dependency injection by tests @@ -184,11 +181,8 @@ func (o ChainOpts) Validate() error { if o.MailMon == nil { err = errors.Join(err, errors.New("nil MailMon")) } - if o.SqlxDB == nil { - err = errors.Join(err, errors.New("nil SqlxDB")) - } - if o.DB == nil { - err = errors.Join(err, errors.New("nil DB")) + if o.DS == nil { + err = errors.Join(err, errors.New("nil DS")) } if err != nil { err = fmt.Errorf("invalid ChainOpts: %w", err) @@ -229,7 +223,7 @@ func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Nod if !opts.AppConfig.EVMRPCEnabled() { headTracker = headtracker.NullTracker } else if opts.GenHeadTracker == nil { - orm := headtracker.NewORM(*chainID, opts.DB) + orm := headtracker.NewORM(*chainID, opts.DS) headSaver = headtracker.NewHeadSaver(l, orm, cfg.EVM(), cfg.EVM().HeadTracker()) headTracker = headtracker.NewHeadTracker(l, client, cfg.EVM(), cfg.EVM().HeadTracker(), headBroadcaster, headSaver, opts.MailMon) } else { @@ -251,12 +245,12 @@ func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Nod LogPrunePageSize: int64(cfg.EVM().LogPrunePageSize()), BackupPollerBlockDelay: int64(cfg.EVM().BackupLogPollerBlockDelay()), } - logPoller = logpoller.NewLogPoller(logpoller.NewObservedORM(chainID, opts.DB, l), client, l, lpOpts) + logPoller = logpoller.NewLogPoller(logpoller.NewObservedORM(chainID, opts.DS, l), client, l, lpOpts) } } // note: gas estimator is started as a part of the txm - txm, gasEstimator, err := newEvmTxm(opts.SqlxDB, opts.DB, cfg.EVM(), opts.AppConfig.EVMRPCEnabled(), opts.AppConfig.Database(), opts.AppConfig.Database().Listener(), client, l, logPoller, opts) + txm, gasEstimator, err := newEvmTxm(opts.DS, cfg.EVM(), opts.AppConfig.EVMRPCEnabled(), opts.AppConfig.Database(), opts.AppConfig.Database().Listener(), client, l, logPoller, opts) if err != nil { return nil, fmt.Errorf("failed to instantiate EvmTxm for chain with ID %s: %w", chainID.String(), err) } @@ -279,7 +273,7 @@ func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Nod if !opts.AppConfig.EVMRPCEnabled() { logBroadcaster = &log.NullBroadcaster{ErrMsg: fmt.Sprintf("Ethereum is disabled for chain %d", chainID)} } else if opts.GenLogBroadcaster == nil { - logORM := log.NewORM(opts.SqlxDB, *chainID) + logORM := log.NewORM(opts.DS, *chainID) logBroadcaster = log.NewBroadcaster(logORM, client, cfg.EVM(), l, highestSeenHead, opts.MailMon) } else { logBroadcaster = opts.GenLogBroadcaster(chainID) diff --git a/core/chains/legacyevm/chain_test.go b/core/chains/legacyevm/chain_test.go index 5dd7eb1c6ed..c10712d4b6b 100644 --- a/core/chains/legacyevm/chain_test.go +++ b/core/chains/legacyevm/chain_test.go @@ -65,8 +65,7 @@ func TestChainOpts_Validate(t *testing.T) { o := legacyevm.ChainOpts{ AppConfig: tt.fields.AppConfig, MailMon: tt.fields.MailMon, - SqlxDB: tt.fields.DB, - DB: tt.fields.DB, + DS: tt.fields.DB, } if err := o.Validate(); (err != nil) != tt.wantErr { t.Errorf("ChainOpts.Validate() error = %v, wantErr %v", err, tt.wantErr) diff --git a/core/chains/legacyevm/evm_txm.go b/core/chains/legacyevm/evm_txm.go index 6b2d1262ce8..df1f4248ce2 100644 --- a/core/chains/legacyevm/evm_txm.go +++ b/core/chains/legacyevm/evm_txm.go @@ -3,8 +3,6 @@ package legacyevm import ( "fmt" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" @@ -15,8 +13,7 @@ import ( ) func newEvmTxm( - sqlxDB *sqlx.DB, - db sqlutil.DataSource, + ds sqlutil.DataSource, cfg evmconfig.EVM, evmRPCEnabled bool, databaseConfig txmgr.DatabaseConfig, @@ -53,8 +50,7 @@ func newEvmTxm( if opts.GenTxManager == nil { txm, err = txmgr.NewTxm( - sqlxDB, - db, + ds, cfg, txmgr.NewEvmTxmFeeConfig(cfg.GasEstimator()), cfg.Transactions(), diff --git a/core/cmd/eth_keys_commands_test.go b/core/cmd/eth_keys_commands_test.go index 2f22cd1d3ae..64835c7f28b 100644 --- a/core/cmd/eth_keys_commands_test.go +++ b/core/cmd/eth_keys_commands_test.go @@ -182,7 +182,7 @@ func TestShell_CreateETHKey(t *testing.T) { withKey(), withMocks(ethClient), ) - db := app.GetSqlxDB() + db := app.GetDB() client, _ := app.NewShellAndRenderer() cltest.AssertCount(t, db, "evm.key_states", 1) // The initial funding key @@ -306,7 +306,7 @@ func TestShell_ImportExportETHKey_NoChains(t *testing.T) { _, err = ethKeyStore.Get(testutils.Context(t), address) require.Error(t, err) - cltest.AssertCount(t, app.GetSqlxDB(), "evm.key_states", 0) + cltest.AssertCount(t, app.GetDB(), "evm.key_states", 0) // Import the key set = flag.NewFlagSet("test", 0) diff --git a/core/cmd/evm_transaction_commands_test.go b/core/cmd/evm_transaction_commands_test.go index df5d066927a..5375abbacee 100644 --- a/core/cmd/evm_transaction_commands_test.go +++ b/core/cmd/evm_transaction_commands_test.go @@ -32,7 +32,7 @@ func TestShell_IndexTransactions(t *testing.T) { _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) - txStore := cltest.NewTestTxStore(t, app.GetSqlxDB()) + txStore := cltest.NewTestTxStore(t, app.GetDB()) tx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, from) attempt := tx.TxAttempts[0] @@ -70,7 +70,7 @@ func TestShell_ShowTransaction(t *testing.T) { app := startNewApplicationV2(t, nil) client, r := app.NewShellAndRenderer() - db := app.GetSqlxDB() + db := app.GetDB() _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) txStore := cltest.NewTestTxStore(t, db) @@ -97,7 +97,7 @@ func TestShell_IndexTxAttempts(t *testing.T) { _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) - txStore := cltest.NewTestTxStore(t, app.GetSqlxDB()) + txStore := cltest.NewTestTxStore(t, app.GetDB()) tx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, from) // page 1 @@ -156,7 +156,7 @@ func TestShell_SendEther_From_Txm(t *testing.T) { withMocks(ethMock, key), ) client, r := app.NewShellAndRenderer() - db := app.GetSqlxDB() + db := app.GetDB() txStore := txmgr.NewTxStore(db, logger.TestLogger(t)) set := flag.NewFlagSet("sendether", 0) flagSetApplyFromAction(client.SendEther, set, "") @@ -221,7 +221,7 @@ func TestShell_SendEther_From_Txm_WEI(t *testing.T) { withMocks(ethMock, key), ) client, r := app.NewShellAndRenderer() - db := app.GetSqlxDB() + db := app.GetDB() txStore := txmgr.NewTxStore(db, logger.TestLogger(t)) set := flag.NewFlagSet("sendether", 0) diff --git a/core/cmd/jobs_commands_test.go b/core/cmd/jobs_commands_test.go index 75e95db84ca..77d2487509a 100644 --- a/core/cmd/jobs_commands_test.go +++ b/core/cmd/jobs_commands_test.go @@ -17,6 +17,7 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/store/models" @@ -428,7 +429,8 @@ func TestShell_DeleteJob(t *testing.T) { requireJobsCount(t, app.JobORM(), 1) - jobs, _, err := app.JobORM().FindJobs(0, 1000) + ctx := testutils.Context(t) + jobs, _, err := app.JobORM().FindJobs(ctx, 0, 1000) require.NoError(t, err) jobID := jobs[0].ID cltest.AwaitJobActive(t, app.JobSpawner(), jobID, 3*time.Second) @@ -451,7 +453,8 @@ func TestShell_DeleteJob(t *testing.T) { } func requireJobsCount(t *testing.T, orm job.ORM, expected int) { - jobs, _, err := orm.FindJobs(0, 1000) + ctx := testutils.Context(t) + jobs, _, err := orm.FindJobs(ctx, 0, 1000) require.NoError(t, err) require.Len(t, jobs, expected) } diff --git a/core/cmd/shell.go b/core/cmd/shell.go index bc58c5cab6d..0372148e742 100644 --- a/core/cmd/shell.go +++ b/core/cmd/shell.go @@ -136,7 +136,7 @@ type AppFactory interface { type ChainlinkAppFactory struct{} // NewApplication returns a new instance of the node with the given config. -func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, appLggr logger.Logger, sqlxDB *sqlx.DB) (app chainlink.Application, err error) { +func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, appLggr logger.Logger, db *sqlx.DB) (app chainlink.Application, err error) { err = initGlobals(cfg.Prometheus(), cfg.Tracing(), appLggr) if err != nil { appLggr.Errorf("Failed to initialize globals: %v", err) @@ -147,14 +147,14 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G return nil, err } - db := sqlutil.WrapDataSource(sqlxDB, appLggr, sqlutil.TimeoutHook(cfg.Database().DefaultQueryTimeout), sqlutil.MonitorHook(cfg.Database().LogSQL)) - - err = handleNodeVersioning(ctx, sqlxDB, appLggr, cfg.RootDir(), cfg.Database(), cfg.WebServer().HTTPPort()) + err = handleNodeVersioning(ctx, db, appLggr, cfg.RootDir(), cfg.Database(), cfg.WebServer().HTTPPort()) if err != nil { return nil, err } - keyStore := keystore.New(db, utils.GetScryptParams(cfg), appLggr) + ds := sqlutil.WrapDataSource(db, appLggr, sqlutil.TimeoutHook(cfg.Database().DefaultQueryTimeout), sqlutil.MonitorHook(cfg.Database().LogSQL)) + + keyStore := keystore.New(ds, utils.GetScryptParams(cfg), appLggr) mailMon := mailbox.NewMonitor(cfg.AppID().String(), appLggr.Named("Mailbox")) loopRegistry := plugins.NewLoopRegistry(appLggr, cfg.Tracing()) @@ -175,7 +175,7 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G evmFactoryCfg := chainlink.EVMFactoryConfig{ CSAETHKeystore: keyStore, - ChainOpts: legacyevm.ChainOpts{AppConfig: cfg, MailMon: mailMon, SqlxDB: sqlxDB, DB: sqlxDB}, + ChainOpts: legacyevm.ChainOpts{AppConfig: cfg, MailMon: mailMon, DS: ds}, } // evm always enabled for backward compatibility // TODO BCF-2510 this needs to change in order to clear the path for EVM extraction @@ -185,8 +185,7 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G cosmosCfg := chainlink.CosmosFactoryConfig{ Keystore: keyStore.Cosmos(), TOMLConfigs: cfg.CosmosConfigs(), - DB: sqlxDB, - QConfig: cfg.Database(), + DS: ds, } initOps = append(initOps, chainlink.InitCosmos(ctx, relayerFactory, cosmosCfg)) } @@ -219,11 +218,10 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G restrictedClient := clhttp.NewRestrictedHTTPClient(cfg.Database(), appLggr) unrestrictedClient := clhttp.NewUnrestrictedHTTPClient() - externalInitiatorManager := webhook.NewExternalInitiatorManager(sqlxDB, unrestrictedClient, appLggr, cfg.Database()) + externalInitiatorManager := webhook.NewExternalInitiatorManager(ds, unrestrictedClient) return chainlink.NewApplication(chainlink.ApplicationOpts{ Config: cfg, - SqlxDB: sqlxDB, - DB: db, + DS: ds, KeyStore: keyStore, RelayerChainInteroperators: relayChainInterops, MailMon: mailMon, @@ -244,7 +242,7 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G func handleNodeVersioning(ctx context.Context, db *sqlx.DB, appLggr logger.Logger, rootDir string, cfg config.Database, healthReportPort uint16) error { var err error // Set up the versioning Configs - verORM := versioning.NewORM(db, appLggr, cfg.DefaultQueryTimeout()) + verORM := versioning.NewORM(db, appLggr) if static.Version != static.Unset { var appv, dbv *semver.Version @@ -272,7 +270,7 @@ func handleNodeVersioning(ctx context.Context, db *sqlx.DB, appLggr logger.Logge // Migrate the database if cfg.MigrateDatabase() { - if err = migrate.Migrate(ctx, db.DB, appLggr); err != nil { + if err = migrate.Migrate(ctx, db.DB); err != nil { return fmt.Errorf("initializeORM#Migrate: %w", err) } } diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go index a61390a4886..6dbffbe404a 100644 --- a/core/cmd/shell_local.go +++ b/core/cmd/shell_local.go @@ -632,7 +632,7 @@ func (s *Shell) RebroadcastTransactions(c *cli.Context) (err error) { s.Logger.Infof("Rebroadcasting transactions from %v to %v", beginningNonce, endingNonce) - orm := txmgr.NewTxStore(app.GetSqlxDB(), lggr) + orm := txmgr.NewTxStore(app.GetDB(), lggr) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), chain.Config().EVM().GasEstimator(), keyStore.Eth(), nil) cfg := txmgr.NewEvmTxmConfig(chain.Config().EVM()) feeCfg := txmgr.NewEvmTxmFeeConfig(chain.Config().EVM().GasEstimator()) @@ -923,7 +923,7 @@ func (s *Shell) RollbackDatabase(c *cli.Context) error { return fmt.Errorf("failed to initialize orm: %v", err) } - if err := migrate.Rollback(ctx, db.DB, s.Logger, version); err != nil { + if err := migrate.Rollback(ctx, db.DB, version); err != nil { return fmt.Errorf("migrateDB failed: %v", err) } @@ -938,7 +938,7 @@ func (s *Shell) VersionDatabase(_ *cli.Context) error { return fmt.Errorf("failed to initialize orm: %v", err) } - version, err := migrate.Current(ctx, db.DB, s.Logger) + version, err := migrate.Current(ctx, db.DB) if err != nil { return fmt.Errorf("migrateDB failed: %v", err) } @@ -955,7 +955,7 @@ func (s *Shell) StatusDatabase(_ *cli.Context) error { return fmt.Errorf("failed to initialize orm: %v", err) } - if err = migrate.Status(ctx, db.DB, s.Logger); err != nil { + if err = migrate.Status(ctx, db.DB); err != nil { return fmt.Errorf("Status failed: %v", err) } return nil @@ -1099,7 +1099,7 @@ func migrateDB(ctx context.Context, config dbConfig, lggr logger.Logger) error { return fmt.Errorf("failed to initialize orm: %v", err) } - if err = migrate.Migrate(ctx, db.DB, lggr); err != nil { + if err = migrate.Migrate(ctx, db.DB); err != nil { return fmt.Errorf("migrateDB failed: %v", err) } return db.Close() @@ -1110,10 +1110,10 @@ func downAndUpDB(ctx context.Context, cfg dbConfig, lggr logger.Logger, baseVers if err != nil { return fmt.Errorf("failed to initialize orm: %v", err) } - if err = migrate.Rollback(ctx, db.DB, lggr, null.IntFrom(baseVersionID)); err != nil { + if err = migrate.Rollback(ctx, db.DB, null.IntFrom(baseVersionID)); err != nil { return fmt.Errorf("test rollback failed: %v", err) } - if err = migrate.Migrate(ctx, db.DB, lggr); err != nil { + if err = migrate.Migrate(ctx, db.DB); err != nil { return fmt.Errorf("second migrateDB failed: %v", err) } return db.Close() diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index d608d3931d0..7427e6caedb 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -91,8 +91,7 @@ func TestShell_RunNodeWithPasswords(t *testing.T) { ChainOpts: legacyevm.ChainOpts{ AppConfig: cfg, MailMon: &mailbox.Monitor{}, - SqlxDB: db, - DB: db, + DS: db, }, } testRelayers := genTestEVMRelayers(t, opts, keyStore) @@ -196,8 +195,7 @@ func TestShell_RunNodeWithAPICredentialsFile(t *testing.T) { ChainOpts: legacyevm.ChainOpts{ AppConfig: cfg, MailMon: &mailbox.Monitor{}, - SqlxDB: db, - DB: db, + DS: db, }, } testRelayers := genTestEVMRelayers(t, opts, keyStore) @@ -299,7 +297,7 @@ func TestShell_RebroadcastTransactions_Txm(t *testing.T) { lggr := logger.TestLogger(t) app := mocks.NewApplication(t) - app.On("GetSqlxDB").Return(sqlxDB) + app.On("GetDB").Return(sqlxDB) app.On("GetKeyStore").Return(keyStore) app.On("ID").Maybe().Return(uuid.New()) app.On("GetConfig").Return(config) @@ -381,7 +379,7 @@ func TestShell_RebroadcastTransactions_OutsideRange_Txm(t *testing.T) { lggr := logger.TestLogger(t) app := mocks.NewApplication(t) - app.On("GetSqlxDB").Return(sqlxDB) + app.On("GetDB").Return(sqlxDB) app.On("GetKeyStore").Return(keyStore) app.On("ID").Maybe().Return(uuid.New()) app.On("GetConfig").Return(config) @@ -460,7 +458,7 @@ func TestShell_RebroadcastTransactions_AddressCheck(t *testing.T) { lggr := logger.TestLogger(t) app := mocks.NewApplication(t) - app.On("GetSqlxDB").Maybe().Return(sqlxDB) + app.On("GetDB").Maybe().Return(sqlxDB) app.On("GetKeyStore").Return(keyStore) app.On("ID").Maybe().Return(uuid.New()) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) diff --git a/core/cmd/shell_remote_test.go b/core/cmd/shell_remote_test.go index a8c054cd9be..cdbe12d66b4 100644 --- a/core/cmd/shell_remote_test.go +++ b/core/cmd/shell_remote_test.go @@ -151,6 +151,7 @@ func TestShell_CreateExternalInitiator(t *testing.T) { for _, tt := range tests { test := tt t.Run(test.name, func(t *testing.T) { + ctx := testutils.Context(t) app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.JobPipeline.ExternalInitiatorsEnabled = ptr(true) }) @@ -165,7 +166,7 @@ func TestShell_CreateExternalInitiator(t *testing.T) { require.NoError(t, err) var exi bridges.ExternalInitiator - err = app.GetSqlxDB().Get(&exi, `SELECT * FROM external_initiators WHERE name = $1`, test.args[0]) + err = app.GetDB().GetContext(ctx, &exi, `SELECT * FROM external_initiators WHERE name = $1`, test.args[0]) require.NoError(t, err) if len(test.args) > 1 { @@ -195,7 +196,7 @@ func TestShell_CreateExternalInitiator_Errors(t *testing.T) { }) client, _ := app.NewShellAndRenderer() - initialExis := len(cltest.AllExternalInitiators(t, app.GetSqlxDB())) + initialExis := len(cltest.AllExternalInitiators(t, app.GetDB())) set := flag.NewFlagSet("create", 0) flagSetApplyFromAction(client.CreateExternalInitiator, set, "") @@ -206,7 +207,7 @@ func TestShell_CreateExternalInitiator_Errors(t *testing.T) { err := client.CreateExternalInitiator(c) assert.Error(t, err) - exis := cltest.AllExternalInitiators(t, app.GetSqlxDB()) + exis := cltest.AllExternalInitiators(t, app.GetDB()) assert.Len(t, exis, initialExis) }) } @@ -580,8 +581,8 @@ func TestShell_RunOCRJob_HappyPath(t *testing.T) { require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) - _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) - _, bridge2 := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) + _, bridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) + _, bridge2 := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) var jb job.Job ocrspec := testspecs.GenerateOCRSpec(testspecs.OCRSpecParams{DS1BridgeName: bridge.Name.String(), DS2BridgeName: bridge2.Name.String()}) @@ -669,7 +670,7 @@ func TestShell_AutoLogin(t *testing.T) { require.NoError(t, err) // Expire the session and then try again - pgtest.MustExec(t, app.GetSqlxDB(), "delete from sessions where email = $1", user.Email) + pgtest.MustExec(t, app.GetDB(), "delete from sessions where email = $1", user.Email) err = client.ListJobs(cli.NewContext(nil, fs, nil)) require.NoError(t, err) } diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index 8123439dafb..dc7079e44d9 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -181,11 +181,11 @@ type JobPipelineConfig interface { MaxSuccessfulRuns() uint64 } -func NewJobPipelineV2(t testing.TB, cfg pipeline.BridgeConfig, jpcfg JobPipelineConfig, dbCfg pg.QConfig, legacyChains legacyevm.LegacyChainContainer, db *sqlx.DB, keyStore keystore.Master, restrictedHTTPClient, unrestrictedHTTPClient *http.Client) JobPipelineV2TestHelper { +func NewJobPipelineV2(t testing.TB, cfg pipeline.BridgeConfig, jpcfg JobPipelineConfig, legacyChains legacyevm.LegacyChainContainer, db *sqlx.DB, keyStore keystore.Master, restrictedHTTPClient, unrestrictedHTTPClient *http.Client) JobPipelineV2TestHelper { lggr := logger.TestLogger(t) prm := pipeline.NewORM(db, lggr, jpcfg.MaxSuccessfulRuns()) btORM := bridges.NewORM(db) - jrm := job.NewORM(db, prm, btORM, keyStore, lggr, dbCfg) + jrm := job.NewORM(db, prm, btORM, keyStore, lggr) pr := pipeline.NewRunner(prm, btORM, jpcfg, cfg, legacyChains, keyStore.Eth(), keyStore.VRF(), lggr, restrictedHTTPClient, unrestrictedHTTPClient) return JobPipelineV2TestHelper{ prm, @@ -323,6 +323,8 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn require.NoError(t, err) t.Cleanup(func() { assert.NoError(t, db.Close()) }) + ds := sqlutil.WrapDataSource(db, lggr, sqlutil.TimeoutHook(cfg.Database().DefaultQueryTimeout)) + var ethClient evmclient.Client var externalInitiatorManager webhook.ExternalInitiatorManager externalInitiatorManager = &webhook.NullExternalInitiatorManager{} @@ -337,13 +339,13 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn default: switch flag { case UseRealExternalInitiatorManager: - externalInitiatorManager = webhook.NewExternalInitiatorManager(db, clhttptest.NewTestLocalOnlyHTTPClient(), lggr, cfg.Database()) + externalInitiatorManager = webhook.NewExternalInitiatorManager(ds, clhttptest.NewTestLocalOnlyHTTPClient()) } } } - keyStore := keystore.NewInMemory(db, utils.FastScryptParams, lggr) + keyStore := keystore.NewInMemory(ds, utils.FastScryptParams, lggr) mailMon := mailbox.NewMonitor(cfg.AppID().String(), lggr.Named("Mailbox")) loopRegistry := plugins.NewLoopRegistry(lggr, nil) @@ -365,8 +367,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn ChainOpts: legacyevm.ChainOpts{ AppConfig: cfg, MailMon: mailMon, - SqlxDB: db, - DB: db, + DS: ds, }, CSAETHKeystore: keyStore, } @@ -392,8 +393,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn cosmosCfg := chainlink.CosmosFactoryConfig{ Keystore: keyStore.Cosmos(), TOMLConfigs: cfg.CosmosConfigs(), - DB: db, - QConfig: cfg.Database(), + DS: ds, } initOps = append(initOps, chainlink.InitCosmos(testCtx, relayerFactory, cosmosCfg)) } @@ -420,8 +420,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn appInstance, err := chainlink.NewApplication(chainlink.ApplicationOpts{ Config: cfg, MailMon: mailMon, - SqlxDB: db, - DB: db, + DS: ds, KeyStore: keyStore, RelayerChainInteroperators: relayChainInterops, Logger: lggr, @@ -569,9 +568,10 @@ func (ta *TestApplication) Stop() error { } func (ta *TestApplication) MustSeedNewSession(email string) (id string) { + ctx := testutils.Context(ta.t) session := NewSession() ta.Logger.Infof("TestApplication creating session (id: %s, email: %s, last used: %s)", session.ID, email, session.LastUsed.String()) - err := ta.GetSqlxDB().Get(&id, `INSERT INTO sessions (id, email, last_used, created_at) VALUES ($1, $2, $3, NOW()) RETURNING id`, session.ID, email, session.LastUsed) + err := ta.GetDB().GetContext(ctx, &id, `INSERT INTO sessions (id, email, last_used, created_at) VALUES ($1, $2, $3, NOW()) RETURNING id`, session.ID, email, session.LastUsed) require.NoError(ta.t, err) return id } @@ -903,13 +903,14 @@ const ( // WaitForSpecErrorV2 polls until the passed in jobID has count number // of job spec errors. -func WaitForSpecErrorV2(t *testing.T, db *sqlx.DB, jobID int32, count int) []job.SpecError { +func WaitForSpecErrorV2(t *testing.T, ds sqlutil.DataSource, jobID int32, count int) []job.SpecError { t.Helper() + ctx := testutils.Context(t) g := gomega.NewWithT(t) var jse []job.SpecError g.Eventually(func() []job.SpecError { - err := db.Select(&jse, `SELECT * FROM job_spec_errors WHERE job_id = $1`, jobID) + err := ds.SelectContext(ctx, &jse, `SELECT * FROM job_spec_errors WHERE job_id = $1`, jobID) assert.NoError(t, err) return jse }, testutils.WaitTimeout(t), DBPollingInterval).Should(gomega.HaveLen(count)) @@ -930,7 +931,7 @@ func WaitForPipeline(t testing.TB, nodeID int, jobID int32, expectedPipelineRuns var pr []pipeline.Run gomega.NewWithT(t).Eventually(func() bool { - prs, _, err := jo.PipelineRuns(&jobID, 0, 1000) + prs, _, err := jo.PipelineRuns(testutils.Context(t), &jobID, 0, 1000) require.NoError(t, err) var matched []pipeline.Run @@ -964,13 +965,14 @@ func WaitForPipeline(t testing.TB, nodeID int, jobID int32, expectedPipelineRuns } // AssertPipelineRunsStays asserts that the number of pipeline runs for a particular job remains at the provided values -func AssertPipelineRunsStays(t testing.TB, pipelineSpecID int32, db *sqlx.DB, want int) []pipeline.Run { +func AssertPipelineRunsStays(t testing.TB, pipelineSpecID int32, db sqlutil.DataSource, want int) []pipeline.Run { t.Helper() + ctx := testutils.Context(t) g := gomega.NewWithT(t) var prs []pipeline.Run g.Consistently(func() []pipeline.Run { - err := db.Select(&prs, `SELECT * FROM pipeline_runs WHERE pipeline_spec_id = $1`, pipelineSpecID) + err := db.SelectContext(ctx, &prs, `SELECT * FROM pipeline_runs WHERE pipeline_spec_id = $1`, pipelineSpecID) assert.NoError(t, err) return prs }, AssertNoActionTimeout, DBPollingInterval).Should(gomega.HaveLen(want)) @@ -1161,11 +1163,12 @@ func NewSession(optionalSessionID ...string) clsessions.Session { return session } -func AllExternalInitiators(t testing.TB, db *sqlx.DB) []bridges.ExternalInitiator { +func AllExternalInitiators(t testing.TB, ds sqlutil.DataSource) []bridges.ExternalInitiator { t.Helper() + ctx := testutils.Context(t) var all []bridges.ExternalInitiator - err := db.Select(&all, `SELECT * FROM external_initiators`) + err := ds.SelectContext(ctx, &all, `SELECT * FROM external_initiators`) require.NoError(t, err) return all } @@ -1518,35 +1521,38 @@ func AssertCount(t *testing.T, ds sqlutil.DataSource, tableName string, expected testutils.AssertCount(t, ds, tableName, expected) } -func WaitForCount(t *testing.T, db *sqlx.DB, tableName string, want int64) { +func WaitForCount(t *testing.T, ds sqlutil.DataSource, tableName string, want int64) { t.Helper() + ctx := testutils.Context(t) g := gomega.NewWithT(t) var count int64 var err error g.Eventually(func() int64 { - err = db.Get(&count, fmt.Sprintf(`SELECT count(*) FROM %s;`, tableName)) + err = ds.GetContext(ctx, &count, fmt.Sprintf(`SELECT count(*) FROM %s;`, tableName)) assert.NoError(t, err) return count }, testutils.WaitTimeout(t), DBPollingInterval).Should(gomega.Equal(want)) } -func AssertCountStays(t testing.TB, db *sqlx.DB, tableName string, want int64) { +func AssertCountStays(t testing.TB, ds sqlutil.DataSource, tableName string, want int64) { t.Helper() + ctx := testutils.Context(t) g := gomega.NewWithT(t) var count int64 var err error g.Consistently(func() int64 { - err = db.Get(&count, fmt.Sprintf(`SELECT count(*) FROM %s`, tableName)) + err = ds.GetContext(ctx, &count, fmt.Sprintf(`SELECT count(*) FROM %s`, tableName)) assert.NoError(t, err) return count }, AssertNoActionTimeout, DBPollingInterval).Should(gomega.Equal(want)) } -func AssertRecordEventually(t *testing.T, db *sqlx.DB, model interface{}, stmt string, check func() bool) { +func AssertRecordEventually(t *testing.T, ds sqlutil.DataSource, model interface{}, stmt string, check func() bool) { t.Helper() + ctx := testutils.Context(t) g := gomega.NewWithT(t) g.Eventually(func() bool { - err := db.Get(model, stmt) + err := ds.GetContext(ctx, model, stmt) require.NoError(t, err, "unable to find record in DB") return check() }, testutils.WaitTimeout(t), DBPollingInterval).Should(gomega.BeTrue()) diff --git a/core/internal/cltest/factories.go b/core/internal/cltest/factories.go index 43cf902ca8a..cd2fa9d9f63 100644 --- a/core/internal/cltest/factories.go +++ b/core/internal/cltest/factories.go @@ -98,9 +98,9 @@ func NewBridgeType(t testing.TB, opts BridgeOpts) (*bridges.BridgeTypeAuthentica // MustCreateBridge creates a bridge // Be careful not to specify a name here unless you ABSOLUTELY need to // This is because name is a unique index and identical names used across transactional tests will lock/deadlock -func MustCreateBridge(t testing.TB, db *sqlx.DB, opts BridgeOpts) (bta *bridges.BridgeTypeAuthentication, bt *bridges.BridgeType) { +func MustCreateBridge(t testing.TB, ds sqlutil.DataSource, opts BridgeOpts) (bta *bridges.BridgeTypeAuthentication, bt *bridges.BridgeType) { bta, bt = NewBridgeType(t, opts) - orm := bridges.NewORM(db) + orm := bridges.NewORM(ds) err := orm.CreateBridgeType(testutils.Context(t), bt) require.NoError(t, err) return bta, bt @@ -317,9 +317,9 @@ func MustGenerateRandomKeyState(_ testing.TB) ethkey.State { return ethkey.State{Address: NewEIP55Address()} } -func MustInsertHead(t *testing.T, db sqlutil.DataSource, number int64) evmtypes.Head { +func MustInsertHead(t *testing.T, ds sqlutil.DataSource, number int64) evmtypes.Head { h := evmtypes.NewHead(big.NewInt(number), evmutils.NewHash(), evmutils.NewHash(), 0, ubig.New(&FixtureChainID)) - horm := headtracker.NewORM(FixtureChainID, db) + horm := headtracker.NewORM(FixtureChainID, ds) err := horm.IdempotentInsertHead(testutils.Context(t), &h) require.NoError(t, err) @@ -347,8 +347,8 @@ func MustInsertV2JobSpec(t *testing.T, db *sqlx.DB, transmitterAddress common.Ad PipelineSpecID: pipelineSpec.ID, } - jorm := job.NewORM(db, nil, nil, nil, logger.TestLogger(t), configtest.NewTestGeneralConfig(t).Database()) - err = jorm.InsertJob(&jb) + jorm := job.NewORM(db, nil, nil, nil, logger.TestLogger(t)) + err = jorm.InsertJob(testutils.Context(t), &jb) require.NoError(t, err) return jb } @@ -404,8 +404,8 @@ func MustInsertKeeperJob(t *testing.T, db *sqlx.DB, korm *keeper.ORM, from evmty tlg := logger.TestLogger(t) prm := pipeline.NewORM(db, tlg, cfg.JobPipeline().MaxSuccessfulRuns()) btORM := bridges.NewORM(db) - jrm := job.NewORM(db, prm, btORM, nil, tlg, cfg.Database()) - err = jrm.InsertJob(&jb) + jrm := job.NewORM(db, prm, btORM, nil, tlg) + err = jrm.InsertJob(testutils.Context(t), &jb) require.NoError(t, err) jb.PipelineSpec.JobID = jb.ID return jb diff --git a/core/internal/cltest/job_factories.go b/core/internal/cltest/job_factories.go index d78440838b2..6ba13f97726 100644 --- a/core/internal/cltest/job_factories.go +++ b/core/internal/cltest/job_factories.go @@ -7,8 +7,7 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/require" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -43,30 +42,30 @@ func MinimalOCRNonBootstrapSpec(contractAddress, transmitterAddress types.EIP55A return fmt.Sprintf(minimalOCRNonBootstrapTemplate, contractAddress, peerID, transmitterAddress.Hex(), keyBundleID) } -func MustInsertWebhookSpec(t *testing.T, db *sqlx.DB) (job.Job, job.WebhookSpec) { +func MustInsertWebhookSpec(t *testing.T, ds sqlutil.DataSource) (job.Job, job.WebhookSpec) { ctx := testutils.Context(t) - jobORM, pipelineORM := getORMs(t, db) + jobORM, pipelineORM := getORMs(t, ds) webhookSpec := job.WebhookSpec{} - require.NoError(t, jobORM.InsertWebhookSpec(&webhookSpec)) + require.NoError(t, jobORM.InsertWebhookSpec(ctx, &webhookSpec)) pSpec := pipeline.Pipeline{} - pipelineSpecID, err := pipelineORM.CreateSpec(ctx, nil, pSpec, 0) + pipelineSpecID, err := pipelineORM.CreateSpec(ctx, pSpec, 0) require.NoError(t, err) createdJob := job.Job{WebhookSpecID: &webhookSpec.ID, WebhookSpec: &webhookSpec, SchemaVersion: 1, Type: "webhook", ExternalJobID: uuid.New(), PipelineSpecID: pipelineSpecID} - require.NoError(t, jobORM.InsertJob(&createdJob)) + require.NoError(t, jobORM.InsertJob(ctx, &createdJob)) return createdJob, webhookSpec } -func getORMs(t *testing.T, db *sqlx.DB) (jobORM job.ORM, pipelineORM pipeline.ORM) { +func getORMs(t *testing.T, ds sqlutil.DataSource) (jobORM job.ORM, pipelineORM pipeline.ORM) { config := configtest.NewTestGeneralConfig(t) - keyStore := NewKeyStore(t, db) + keyStore := NewKeyStore(t, ds) lggr := logger.TestLogger(t) - pipelineORM = pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) - bridgeORM := bridges.NewORM(db) - jobORM = job.NewORM(db, pipelineORM, bridgeORM, keyStore, lggr, config.Database()) + pipelineORM = pipeline.NewORM(ds, lggr, config.JobPipeline().MaxSuccessfulRuns()) + bridgeORM := bridges.NewORM(ds) + jobORM = job.NewORM(ds, pipelineORM, bridgeORM, keyStore, lggr) t.Cleanup(func() { jobORM.Close() }) return } diff --git a/core/internal/features/features_test.go b/core/internal/features/features_test.go index 75ff98d05be..26e7d5eae56 100644 --- a/core/internal/features/features_test.go +++ b/core/internal/features/features_test.go @@ -82,6 +82,7 @@ var oneETH = assets.Eth(*big.NewInt(1000000000000000000)) func TestIntegration_ExternalInitiatorV2(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -175,7 +176,7 @@ func TestIntegration_ExternalInitiatorV2(t *testing.T) { require.NoError(t, err) })) u, _ := url.Parse(bridgeServer.URL) - err := app.BridgeORM().CreateBridgeType(testutils.Context(t), &bridges.BridgeType{ + err := app.BridgeORM().CreateBridgeType(ctx, &bridges.BridgeType{ Name: bridges.BridgeName("substrate-adapter1"), URL: models.WebURL(*u), }) @@ -205,7 +206,7 @@ observationSource = """ """ `, jobUUID, eiName, cltest.MustJSONMarshal(t, eiSpec)) - _, err := webhook.ValidatedWebhookSpec(tomlSpec, app.GetExternalInitiatorManager()) + _, err := webhook.ValidatedWebhookSpec(ctx, tomlSpec, app.GetExternalInitiatorManager()) require.NoError(t, err) job := cltest.CreateJobViaWeb(t, app, []byte(cltest.MustJSONMarshal(t, web.CreateJobRequest{TOML: tomlSpec}))) jobID = job.ID @@ -227,7 +228,7 @@ observationSource = """ defer cleanup() cltest.AssertServerResponse(t, resp, 401) - cltest.AssertCountStays(t, app.GetSqlxDB(), "pipeline_runs", 0) + cltest.AssertCountStays(t, app.GetDB(), "pipeline_runs", 0) }) t.Run("calling webhook_spec with matching external_initiator_id works", func(t *testing.T) { @@ -236,9 +237,9 @@ observationSource = """ _ = cltest.CreateJobRunViaExternalInitiatorV2(t, app, jobUUID, *eia, cltest.MustJSONMarshal(t, eiRequest)) - pipelineORM := pipeline.NewORM(app.GetSqlxDB(), logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - bridgeORM := bridges.NewORM(app.GetSqlxDB()) - jobORM := job.NewORM(app.GetSqlxDB(), pipelineORM, bridgeORM, app.KeyStore, logger.TestLogger(t), cfg.Database()) + pipelineORM := pipeline.NewORM(app.GetDB(), logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) + bridgeORM := bridges.NewORM(app.GetDB()) + jobORM := job.NewORM(app.GetDB(), pipelineORM, bridgeORM, app.KeyStore, logger.TestLogger(t)) runs := cltest.WaitForPipelineComplete(t, 0, jobID, 1, 2, jobORM, 5*time.Second, 300*time.Millisecond) require.Len(t, runs, 1) @@ -992,8 +993,9 @@ observationSource = """ return answer.String() }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal("20")) + ctx := testutils.Context(t) for _, app := range apps { - jobs, _, err := app.JobORM().FindJobs(0, 1000) + jobs, _, err := app.JobORM().FindJobs(ctx, 0, 1000) require.NoError(t, err) // No spec errors for _, j := range jobs { @@ -1220,8 +1222,9 @@ observationSource = """ return answer.String() }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal("20")) + ctx := testutils.Context(t) for _, app := range apps { - jobs, _, err := app.JobORM().FindJobs(0, 1000) + jobs, _, err := app.JobORM().FindJobs(ctx, 0, 1000) require.NoError(t, err) // No spec errors for _, j := range jobs { diff --git a/core/internal/features/ocr2/features_ocr2_test.go b/core/internal/features/ocr2/features_ocr2_test.go index 07e0fc21d9a..fab9d34b4b1 100644 --- a/core/internal/features/ocr2/features_ocr2_test.go +++ b/core/internal/features/ocr2/features_ocr2_test.go @@ -519,6 +519,7 @@ updateInterval = "1m" } }() + ctx := testutils.Context(t) for trial := 0; trial < 2; trial++ { var retVal int @@ -537,7 +538,7 @@ updateInterval = "1m" wg.Add(1) go func() { defer wg.Done() - completedRuns, err2 := apps[ic].JobORM().FindPipelineRunIDsByJobID(jids[ic], 0, 1000) + completedRuns, err2 := apps[ic].JobORM().FindPipelineRunIDsByJobID(ctx, jids[ic], 0, 1000) require.NoError(t, err2) // Want at least 2 runs so we see all the metadata. pr := cltest.WaitForPipelineComplete(t, ic, jids[ic], len(completedRuns)+2, 7, apps[ic].JobORM(), 2*time.Minute, 5*time.Second) @@ -558,7 +559,7 @@ updateInterval = "1m" }, 1*time.Minute, 200*time.Millisecond).Should(gomega.Equal(fmt.Sprintf("%d", 2*retVal))) for _, app := range apps { - jobs, _, err2 := app.JobORM().FindJobs(0, 1000) + jobs, _, err2 := app.JobORM().FindJobs(ctx, 0, 1000) require.NoError(t, err2) // No spec errors for _, j := range jobs { @@ -758,6 +759,7 @@ chainID = 1337 expectedMeta := map[string]struct{}{ "0": {}, "10": {}, "20": {}, "30": {}, } + ctx := testutils.Context(t) for i := 0; i < 4; i++ { s := i require.NoError(t, apps[i].Start(testutils.Context(t))) @@ -790,7 +792,7 @@ chainID = 1337 servers[s].Close() }) u, _ := url.Parse(servers[i].URL) - require.NoError(t, apps[i].BridgeORM().CreateBridgeType(testutils.Context(t), &bridges.BridgeType{ + require.NoError(t, apps[i].BridgeORM().CreateBridgeType(ctx, &bridges.BridgeType{ Name: bridges.BridgeName(fmt.Sprintf("bridge%d", i)), URL: models.WebURL(*u), })) @@ -882,7 +884,7 @@ updateInterval = "1m" }, 1*time.Minute, 200*time.Millisecond).Should(gomega.Equal("20")) for _, app := range apps { - jobs, _, err := app.JobORM().FindJobs(0, 1000) + jobs, _, err := app.JobORM().FindJobs(ctx, 0, 1000) require.NoError(t, err) // No spec errors for _, j := range jobs { diff --git a/core/internal/mocks/application.go b/core/internal/mocks/application.go index 2438eb302c0..c83b37a0e5d 100644 --- a/core/internal/mocks/application.go +++ b/core/internal/mocks/application.go @@ -35,8 +35,6 @@ import ( sqlutil "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - sqlx "github.com/jmoiron/sqlx" - txmgr "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" types "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -389,26 +387,6 @@ func (_m *Application) GetRelayers() chainlink.RelayerChainInteroperators { return r0 } -// GetSqlxDB provides a mock function with given fields: -func (_m *Application) GetSqlxDB() *sqlx.DB { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for GetSqlxDB") - } - - var r0 *sqlx.DB - if rf, ok := ret.Get(0).(func() *sqlx.DB); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*sqlx.DB) - } - } - - return r0 -} - // GetWebAuthnConfiguration provides a mock function with given fields: func (_m *Application) GetWebAuthnConfiguration() sessions.WebAuthnConfiguration { ret := _m.Called() diff --git a/core/internal/testutils/evmtest/evmtest.go b/core/internal/testutils/evmtest/evmtest.go index eedc6275928..276dea2ac5d 100644 --- a/core/internal/testutils/evmtest/evmtest.go +++ b/core/internal/testutils/evmtest/evmtest.go @@ -9,13 +9,13 @@ import ( "testing" "github.com/ethereum/go-ethereum" - "github.com/jmoiron/sqlx" "github.com/pelletier/go-toml/v2" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox/mailboxtest" @@ -62,7 +62,7 @@ type TestChainOpts struct { LogPoller logpoller.LogPoller GeneralConfig legacyevm.AppConfig HeadTracker httypes.HeadTracker - DB *sqlx.DB + DB sqlutil.DataSource TxManager txmgr.TxManager KeyStore keystore.Eth MailMon *mailbox.Monitor @@ -88,8 +88,7 @@ func NewChainRelayExtOpts(t testing.TB, testopts TestChainOpts) legacyevm.ChainR AppConfig: testopts.GeneralConfig, MailMon: testopts.MailMon, GasEstimator: testopts.GasEstimator, - SqlxDB: testopts.DB, - DB: testopts.DB, + DS: testopts.DB, }, } opts.GenEthClient = func(*big.Int) evmclient.Client { diff --git a/core/internal/testutils/pgtest/pgtest.go b/core/internal/testutils/pgtest/pgtest.go index 686483f2d41..8464604b667 100644 --- a/core/internal/testutils/pgtest/pgtest.go +++ b/core/internal/testutils/pgtest/pgtest.go @@ -1,7 +1,6 @@ package pgtest import ( - "database/sql" "testing" "github.com/google/uuid" @@ -10,25 +9,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/store/dialects" ) -func NewQConfig(logSQL bool) pg.QConfig { - return pg.NewQConfig(logSQL) -} - -func NewSqlDB(t *testing.T) *sql.DB { - testutils.SkipShortDB(t) - db, err := sql.Open(string(dialects.TransactionWrappedPostgres), uuid.New().String()) - require.NoError(t, err) - t.Cleanup(func() { assert.NoError(t, db.Close()) }) - - return db -} - func NewSqlxDB(t testing.TB) *sqlx.DB { testutils.SkipShortDB(t) db, err := sqlx.Open(string(dialects.TransactionWrappedPostgres), uuid.New().String()) @@ -39,12 +25,9 @@ func NewSqlxDB(t testing.TB) *sqlx.DB { return db } -func MustExec(t *testing.T, db *sqlx.DB, stmt string, args ...interface{}) { - require.NoError(t, utils.JustError(db.Exec(stmt, args...))) -} - -func MustSelect(t *testing.T, db *sqlx.DB, dest interface{}, stmt string, args ...interface{}) { - require.NoError(t, db.Select(dest, stmt, args...)) +func MustExec(t *testing.T, ds sqlutil.DataSource, stmt string, args ...interface{}) { + ctx := testutils.Context(t) + require.NoError(t, utils.JustError(ds.ExecContext(ctx, stmt, args...))) } func MustCount(t *testing.T, db *sqlx.DB, stmt string, args ...interface{}) (cnt int) { diff --git a/core/internal/testutils/testutils.go b/core/internal/testutils/testutils.go index ba7e697fb62..f4867eda69a 100644 --- a/core/internal/testutils/testutils.go +++ b/core/internal/testutils/testutils.go @@ -420,8 +420,9 @@ func SkipShortDB(tb testing.TB) { func AssertCount(t *testing.T, ds sqlutil.DataSource, tableName string, expected int64) { t.Helper() + ctx := Context(t) var count int64 - err := ds.GetContext(Context(t), &count, fmt.Sprintf(`SELECT count(*) FROM %s;`, tableName)) + err := ds.GetContext(ctx, &count, fmt.Sprintf(`SELECT count(*) FROM %s;`, tableName)) require.NoError(t, err) require.Equal(t, expected, count) } diff --git a/core/scripts/gateway/run_gateway.go b/core/scripts/gateway/run_gateway.go index 5dbcd02bf56..2daca5190a5 100644 --- a/core/scripts/gateway/run_gateway.go +++ b/core/scripts/gateway/run_gateway.go @@ -48,7 +48,7 @@ func main() { lggr, _ := logger.NewLogger() - handlerFactory := gateway.NewHandlerFactory(nil, nil, nil, lggr) + handlerFactory := gateway.NewHandlerFactory(nil, nil, lggr) gw, err := gateway.NewGatewayFromConfig(&cfg, handlerFactory, lggr) if err != nil { fmt.Println("error creating Gateway object:", err) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 9788679dd98..08050c32167 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -256,7 +256,7 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 // indirect + github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba58 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 45ef18e49ca..48a66de1ec3 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1187,8 +1187,8 @@ github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfs github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 h1:54hM3/SrOM166it2K35hGb5K7gQ49/Op0aHp9WkqpqU= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 h1:MvaNzuaQh1vX4CAYLM8qFd99cf0ZF1JNwtDZtLU7WvU= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee h1:eFuBKyEbL2b+eyfgV/Eu9+8HuCEev+IcBi+K9l1dG7g= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab h1:Ct1oUlyn03HDUVdFHJqtRGRUujMqdoMzvf/Cjhe30Ag= diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index 88a6fadf345..0ac6555aecc 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -16,8 +16,6 @@ import ( "go.uber.org/multierr" "go.uber.org/zap/zapcore" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/chainlink-common/pkg/loop" commonservices "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" @@ -53,7 +51,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" externalp2p "github.com/smartcontractkit/chainlink/v2/core/services/p2p/wrapper" "github.com/smartcontractkit/chainlink/v2/core/services/periodicbackup" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/promreporter" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury" @@ -78,7 +75,6 @@ type Application interface { GetLogger() logger.SugaredLogger GetAuditLogger() audit.AuditLogger GetHealthChecker() services.Checker - GetSqlxDB() *sqlx.DB // Deprecated: use GetDB GetDB() sqlutil.DataSource GetConfig() GeneralConfig SetLogLevel(lvl zapcore.Level) error @@ -146,8 +142,7 @@ type ChainlinkApplication struct { logger logger.SugaredLogger AuditLogger audit.AuditLogger closeLogger func() error - sqlxDB *sqlx.DB // Deprecated: use db instead - db sqlutil.DataSource + ds sqlutil.DataSource secretGenerator SecretGenerator profiler *pyroscope.Profiler loopRegistry *plugins.LoopRegistry @@ -161,8 +156,7 @@ type ApplicationOpts struct { Config GeneralConfig Logger logger.Logger MailMon *mailbox.Monitor - SqlxDB *sqlx.DB // Deprecated: use DB instead - DB sqlutil.DataSource + DS sqlutil.DataSource KeyStore keystore.Master RelayerChainInteroperators *CoreRelayerChainInteroperators AuditLogger audit.AuditLogger @@ -185,7 +179,6 @@ type ApplicationOpts struct { func NewApplication(opts ApplicationOpts) (Application, error) { var srvcs []services.ServiceCtx auditLogger := opts.AuditLogger - sqlxDB := opts.SqlxDB cfg := opts.Config relayerChainInterops := opts.RelayerChainInteroperators mailMon := opts.MailMon @@ -277,12 +270,12 @@ func NewApplication(opts ApplicationOpts) (Application, error) { srvcs = append(srvcs, mailMon) srvcs = append(srvcs, relayerChainInterops.Services()...) - promReporter := promreporter.NewPromReporter(sqlxDB.DB, legacyEVMChains, globalLogger) + promReporter := promreporter.NewPromReporter(opts.DS, legacyEVMChains, globalLogger) srvcs = append(srvcs, promReporter) // Initialize Local Users ORM and Authentication Provider specified in config // BasicAdminUsersORM is initialized and required regardless of separate Authentication Provider - localAdminUsersORM := localauth.NewORM(opts.DB, cfg.WebServer().SessionTimeout().Duration(), globalLogger, auditLogger) + localAdminUsersORM := localauth.NewORM(opts.DS, cfg.WebServer().SessionTimeout().Duration(), globalLogger, auditLogger) // Initialize Sessions ORM based on environment configured authenticator // localDB auth or remote LDAP auth @@ -294,26 +287,26 @@ func NewApplication(opts ApplicationOpts) (Application, error) { case sessions.LDAPAuth: var err error authenticationProvider, err = ldapauth.NewLDAPAuthenticator( - opts.DB, cfg.WebServer().LDAP(), cfg.Insecure().DevWebServer(), globalLogger, auditLogger, + opts.DS, cfg.WebServer().LDAP(), cfg.Insecure().DevWebServer(), globalLogger, auditLogger, ) if err != nil { return nil, errors.Wrap(err, "NewApplication: failed to initialize LDAP Authentication module") } - sessionReaper = ldapauth.NewLDAPServerStateSync(sqlxDB, cfg.Database(), cfg.WebServer().LDAP(), globalLogger) + sessionReaper = ldapauth.NewLDAPServerStateSync(opts.DS, cfg.WebServer().LDAP(), globalLogger) case sessions.LocalAuth: - authenticationProvider = localauth.NewORM(opts.DB, cfg.WebServer().SessionTimeout().Duration(), globalLogger, auditLogger) - sessionReaper = localauth.NewSessionReaper(sqlxDB.DB, cfg.WebServer(), globalLogger) + authenticationProvider = localauth.NewORM(opts.DS, cfg.WebServer().SessionTimeout().Duration(), globalLogger, auditLogger) + sessionReaper = localauth.NewSessionReaper(opts.DS, cfg.WebServer(), globalLogger) default: return nil, errors.Errorf("NewApplication: Unexpected 'AuthenticationMethod': %s supported values: %s, %s", authMethod, sessions.LocalAuth, sessions.LDAPAuth) } var ( - pipelineORM = pipeline.NewORM(sqlxDB, globalLogger, cfg.JobPipeline().MaxSuccessfulRuns()) - bridgeORM = bridges.NewORM(sqlxDB) - mercuryORM = mercury.NewORM(opts.DB) + pipelineORM = pipeline.NewORM(opts.DS, globalLogger, cfg.JobPipeline().MaxSuccessfulRuns()) + bridgeORM = bridges.NewORM(opts.DS) + mercuryORM = mercury.NewORM(opts.DS) pipelineRunner = pipeline.NewRunner(pipelineORM, bridgeORM, cfg.JobPipeline(), cfg.WebServer(), legacyEVMChains, keyStore.Eth(), keyStore.VRF(), globalLogger, restrictedHTTPClient, unrestrictedHTTPClient) - jobORM = job.NewORM(sqlxDB, pipelineORM, bridgeORM, keyStore, globalLogger, cfg.Database()) - txmORM = txmgr.NewTxStore(opts.DB, globalLogger) + jobORM = job.NewORM(opts.DS, pipelineORM, bridgeORM, keyStore, globalLogger) + txmORM = txmgr.NewTxStore(opts.DS, globalLogger) streamRegistry = streams.NewRegistry(globalLogger, pipelineRunner) ) @@ -334,14 +327,14 @@ func NewApplication(opts ApplicationOpts) (Application, error) { mailMon), job.Keeper: keeper.NewDelegate( cfg, - sqlxDB, + opts.DS, jobORM, pipelineRunner, globalLogger, legacyEVMChains, mailMon), job.VRF: vrf.NewDelegate( - sqlxDB, + opts.DS, keyStore, pipelineRunner, pipelineORM, @@ -368,8 +361,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { job.Gateway: gateway.NewDelegate( legacyEVMChains, keyStore.Eth(), - sqlxDB, - cfg.Database(), + opts.DS, globalLogger), job.Stream: streams.NewDelegate( globalLogger, @@ -395,7 +387,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { jobORM, pipelineORM, pipelineRunner, - sqlxDB, + opts.DS, legacyEVMChains, globalLogger, ) @@ -408,7 +400,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { if err := ocrcommon.ValidatePeerWrapperConfig(cfg.P2P()); err != nil { return nil, err } - peerWrapper = ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), cfg.Database(), sqlxDB, globalLogger) + peerWrapper = ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), opts.DS, globalLogger) srvcs = append(srvcs, peerWrapper) } else { return nil, fmt.Errorf("P2P stack required for OCR or OCR2") @@ -416,7 +408,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { if cfg.OCR().Enabled() { delegates[job.OffchainReporting] = ocr.NewDelegate( - sqlxDB, + opts.DS, jobORM, keyStore, pipelineRunner, @@ -436,11 +428,10 @@ func NewApplication(opts ApplicationOpts) (Application, error) { if cfg.OCR2().Enabled() { globalLogger.Debug("Off-chain reporting v2 enabled") - ocr2DelegateConfig := ocr2.NewDelegateConfig(cfg.OCR2(), cfg.Mercury(), cfg.Threshold(), cfg.Insecure(), cfg.JobPipeline(), cfg.Database(), loopRegistrarConfig) + ocr2DelegateConfig := ocr2.NewDelegateConfig(cfg.OCR2(), cfg.Mercury(), cfg.Threshold(), cfg.Insecure(), cfg.JobPipeline(), loopRegistrarConfig) delegates[job.OffchainReporting2] = ocr2.NewDelegate( - sqlxDB, - opts.DB, + opts.DS, jobORM, bridgeORM, mercuryORM, @@ -460,7 +451,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { registry, ) delegates[job.Bootstrap] = ocrbootstrap.NewDelegateBootstrap( - sqlxDB, + opts.DS, jobORM, peerWrapper, globalLogger, @@ -478,7 +469,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { for _, c := range legacyEVMChains.Slice() { lbs = append(lbs, c.LogBroadcaster()) } - jobSpawner := job.NewSpawner(jobORM, cfg.Database(), healthChecker, delegates, sqlxDB, globalLogger, lbs) + jobSpawner := job.NewSpawner(jobORM, cfg.Database(), healthChecker, delegates, globalLogger, lbs) srvcs = append(srvcs, jobSpawner, pipelineRunner) // We start the log poller after the job spawner @@ -491,11 +482,11 @@ func NewApplication(opts ApplicationOpts) (Application, error) { var feedsService feeds.Service if cfg.Feature().FeedsManager() { - feedsORM := feeds.NewORM(sqlxDB, opts.Logger, cfg.Database()) + feedsORM := feeds.NewORM(opts.DS) feedsService = feeds.NewService( feedsORM, jobORM, - sqlxDB, + opts.DS, jobSpawner, keyStore, cfg, @@ -503,7 +494,6 @@ func NewApplication(opts ApplicationOpts) (Application, error) { cfg.JobPipeline(), cfg.OCR(), cfg.OCR2(), - cfg.Database(), legacyEVMChains, globalLogger, opts.Version, @@ -548,8 +538,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { loopRegistry: loopRegistry, loopRegistrarConfig: loopRegistrarConfig, - sqlxDB: opts.SqlxDB, - db: opts.DB, + ds: opts.DS, // NOTE: Can keep things clean by putting more things in srvcs instead of manually start/closing srvcs: srvcs, @@ -742,7 +731,7 @@ func (app *ChainlinkApplication) WakeSessionReaper() { } func (app *ChainlinkApplication) AddJobV2(ctx context.Context, j *job.Job) error { - return app.jobSpawner.CreateJob(j, pg.WithParentCtx(ctx)) + return app.jobSpawner.CreateJob(ctx, nil, j) } func (app *ChainlinkApplication) DeleteJob(ctx context.Context, jobID int32) error { @@ -756,7 +745,7 @@ func (app *ChainlinkApplication) DeleteJob(ctx context.Context, jobID int32) err return errors.New("job must be deleted in the feeds manager") } - return app.jobSpawner.DeleteJob(jobID, pg.WithParentCtx(ctx)) + return app.jobSpawner.DeleteJob(ctx, nil, jobID) } func (app *ChainlinkApplication) RunWebhookJobV2(ctx context.Context, jobUUID uuid.UUID, requestBody string, meta jsonserializable.JSONSerializable) (int64, error) { @@ -857,12 +846,8 @@ func (app *ChainlinkApplication) GetRelayers() RelayerChainInteroperators { return app.relayers } -func (app *ChainlinkApplication) GetSqlxDB() *sqlx.DB { - return app.sqlxDB -} - func (app *ChainlinkApplication) GetDB() sqlutil.DataSource { - return app.db + return app.ds } // Returns the configuration to use for creating and authenticating diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index 7126c73927c..8111c1f61b4 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -212,8 +212,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { ChainOpts: legacyevm.ChainOpts{ AppConfig: cfg, MailMon: &mailbox.Monitor{}, - SqlxDB: db, - DB: db, + DS: db, }, CSAETHKeystore: keyStore, }), @@ -265,8 +264,8 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { chainlink.InitCosmos(testctx, factory, chainlink.CosmosFactoryConfig{ Keystore: keyStore.Cosmos(), TOMLConfigs: cfg.CosmosConfigs(), - DB: db, - QConfig: cfg.Database()}), + DS: db, + }), }, expectedCosmosChainCnt: 2, expectedCosmosNodeCnt: 2, @@ -287,8 +286,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { AppConfig: cfg, MailMon: &mailbox.Monitor{}, - SqlxDB: db, - DB: db, + DS: db, }, CSAETHKeystore: keyStore, }), @@ -298,8 +296,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { chainlink.InitCosmos(testctx, factory, chainlink.CosmosFactoryConfig{ Keystore: keyStore.Cosmos(), TOMLConfigs: cfg.CosmosConfigs(), - DB: db, - QConfig: cfg.Database(), + DS: db, }), }, expectedEVMChainCnt: 2, diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index 5902555f79c..00db81cce37 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -5,10 +5,10 @@ import ( "errors" "fmt" - "github.com/jmoiron/sqlx" "github.com/pelletier/go-toml/v2" "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos" coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config" @@ -22,7 +22,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/relay" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc" @@ -68,9 +67,7 @@ func (r *RelayerFactory) NewEVM(ctx context.Context, config EVMFactoryConfig) (m } relayerOpts := evmrelay.RelayerOpts{ - DB: ccOpts.SqlxDB, - DS: ccOpts.DB, - QConfig: ccOpts.AppConfig.Database(), + DS: ccOpts.DS, CSAETHKeystore: config.CSAETHKeystore, MercuryPool: r.MercuryPool, } @@ -239,8 +236,7 @@ func (r *RelayerFactory) NewStarkNet(ks keystore.StarkNet, chainCfgs config.TOML type CosmosFactoryConfig struct { Keystore keystore.Cosmos coscfg.TOMLConfigs - *sqlx.DB - pg.QConfig + DS sqlutil.DataSource } func (c CosmosFactoryConfig) Validate() error { @@ -251,11 +247,8 @@ func (c CosmosFactoryConfig) Validate() error { if len(c.TOMLConfigs) == 0 { err = errors.Join(err, fmt.Errorf("no CosmosConfigs provided")) } - if c.DB == nil { - err = errors.Join(err, fmt.Errorf("nil DB")) - } - if c.QConfig == nil { - err = errors.Join(err, fmt.Errorf("nil QConfig")) + if c.DS == nil { + err = errors.Join(err, fmt.Errorf("nil DataStore")) } if err != nil { @@ -284,7 +277,7 @@ func (r *RelayerFactory) NewCosmos(config CosmosFactoryConfig) (map[types.RelayI opts := cosmos.ChainOpts{ Logger: lggr, - DB: config.DB, + DS: config.DS, KeyStore: loopKs, } diff --git a/core/services/cron/cron_test.go b/core/services/cron/cron_test.go index b31a06a9591..38684e982d9 100644 --- a/core/services/cron/cron_test.go +++ b/core/services/cron/cron_test.go @@ -29,7 +29,7 @@ func TestCronV2Pipeline(t *testing.T) { lggr := logger.TestLogger(t) orm := pipeline.NewORM(db, lggr, cfg.JobPipeline().MaxSuccessfulRuns()) btORM := bridges.NewORM(db) - jobORM := job.NewORM(db, orm, btORM, keyStore, lggr, cfg.Database()) + jobORM := job.NewORM(db, orm, btORM, keyStore, lggr) jb := &job.Job{ Type: job.Cron, @@ -40,7 +40,7 @@ func TestCronV2Pipeline(t *testing.T) { } delegate := cron.NewDelegate(runner, lggr) - require.NoError(t, jobORM.CreateJob(jb)) + require.NoError(t, jobORM.CreateJob(testutils.Context(t), jb)) serviceArray, err := delegate.ServicesForSpec(testutils.Context(t), *jb) require.NoError(t, err) assert.Len(t, serviceArray, 1) diff --git a/core/services/directrequest/delegate.go b/core/services/directrequest/delegate.go index 33a0a7e73da..26f2c5f9c84 100644 --- a/core/services/directrequest/delegate.go +++ b/core/services/directrequest/delegate.go @@ -215,36 +215,37 @@ func (l *listener) HandleLog(ctx context.Context, lb log.Broadcast) { } func (l *listener) processOracleRequests() { + ctx, cancel := l.chStop.NewCtx() + defer cancel() for { select { case <-l.chStop: l.shutdownWaitGroup.Done() return case <-l.mbOracleRequests.Notify(): - l.handleReceivedLogs(l.mbOracleRequests) + l.handleReceivedLogs(ctx, l.mbOracleRequests) } } } func (l *listener) processCancelOracleRequests() { + ctx, cancel := l.chStop.NewCtx() + defer cancel() for { select { case <-l.chStop: l.shutdownWaitGroup.Done() return case <-l.mbOracleCancelRequests.Notify(): - l.handleReceivedLogs(l.mbOracleCancelRequests) + l.handleReceivedLogs(ctx, l.mbOracleCancelRequests) } } } -func (l *listener) handleReceivedLogs(mailbox *mailbox.Mailbox[log.Broadcast]) { - ctx, cancel := l.chStop.NewCtx() - defer cancel() - +func (l *listener) handleReceivedLogs(ctx context.Context, mailbox *mailbox.Mailbox[log.Broadcast]) { for { select { - case <-l.chStop: + case <-ctx.Done(): return default: } @@ -263,7 +264,7 @@ func (l *listener) handleReceivedLogs(mailbox *mailbox.Mailbox[log.Broadcast]) { logJobSpecID := lb.RawLog().Topics[1] if logJobSpecID == (common.Hash{}) || (logJobSpecID != l.job.ExternalIDEncodeStringToTopic() && logJobSpecID != l.job.ExternalIDEncodeBytesToTopic()) { l.logger.Debugw("Skipping Run for Log with wrong Job ID", "logJobSpecID", logJobSpecID) - l.markLogConsumed(ctx, lb) + l.markLogConsumed(ctx, nil, lb) continue } @@ -277,7 +278,7 @@ func (l *listener) handleReceivedLogs(mailbox *mailbox.Mailbox[log.Broadcast]) { case *operator_wrapper.OperatorOracleRequest: l.handleOracleRequest(ctx, log, lb) case *operator_wrapper.OperatorCancelOracleRequest: - l.handleCancelOracleRequest(ctx, log, lb) + l.handleCancelOracleRequest(ctx, nil, log, lb) default: l.logger.Warnf("Unexpected log type %T", log) } @@ -316,7 +317,7 @@ func (l *listener) handleOracleRequest(ctx context.Context, request *operator_wr "requester", request.Requester, "allowedRequesters", l.requesters.ToStrings(), ) - l.markLogConsumed(ctx, lb) + l.markLogConsumed(ctx, nil, lb) return } @@ -333,7 +334,7 @@ func (l *listener) handleOracleRequest(ctx context.Context, request *operator_wr "minContractPayment", minContractPayment.String(), "requestPayment", requestPayment.String(), ) - l.markLogConsumed(ctx, lb) + l.markLogConsumed(ctx, nil, lb) return } } @@ -375,7 +376,7 @@ func (l *listener) handleOracleRequest(ctx context.Context, request *operator_wr }) run := pipeline.NewRun(*l.job.PipelineSpec, vars) _, err := l.pipelineRunner.Run(ctx, run, l.logger, true, func(tx sqlutil.DataSource) error { - l.markLogConsumed(ctx, lb) + l.markLogConsumed(ctx, tx, lb) return nil }) if ctx.Err() != nil { @@ -398,16 +399,16 @@ func (l *listener) allowRequester(requester common.Address) bool { } // Cancels runs that haven't been started yet, with the given request ID -func (l *listener) handleCancelOracleRequest(ctx context.Context, request *operator_wrapper.OperatorCancelOracleRequest, lb log.Broadcast) { +func (l *listener) handleCancelOracleRequest(ctx context.Context, ds sqlutil.DataSource, request *operator_wrapper.OperatorCancelOracleRequest, lb log.Broadcast) { runCloserChannelIf, loaded := l.runs.LoadAndDelete(formatRequestId(request.RequestId)) if loaded { close(runCloserChannelIf.(services.StopChan)) } - l.markLogConsumed(ctx, lb) + l.markLogConsumed(ctx, ds, lb) } -func (l *listener) markLogConsumed(ctx context.Context, lb log.Broadcast) { - if err := l.logBroadcaster.MarkConsumed(ctx, nil, lb); err != nil { +func (l *listener) markLogConsumed(ctx context.Context, ds sqlutil.DataSource, lb log.Broadcast) { + if err := l.logBroadcaster.MarkConsumed(ctx, ds, lb); err != nil { l.logger.Errorw("Unable to mark log consumed", "err", err, "log", lb.String()) } } diff --git a/core/services/directrequest/delegate_test.go b/core/services/directrequest/delegate_test.go index 08f38865bec..e754713b010 100644 --- a/core/services/directrequest/delegate_test.go +++ b/core/services/directrequest/delegate_test.go @@ -90,7 +90,7 @@ func NewDirectRequestUniverseWithConfig(t *testing.T, cfg chainlink.GeneralConfi lggr := logger.TestLogger(t) orm := pipeline.NewORM(db, lggr, cfg.JobPipeline().MaxSuccessfulRuns()) btORM := bridges.NewORM(db) - jobORM := job.NewORM(db, orm, btORM, keyStore, lggr, cfg.Database()) + jobORM := job.NewORM(db, orm, btORM, keyStore, lggr) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) delegate := directrequest.NewDelegate(lggr, runner, orm, legacyChains, mailMon) @@ -99,8 +99,9 @@ func NewDirectRequestUniverseWithConfig(t *testing.T, cfg chainlink.GeneralConfi if specF != nil { specF(jb) } - require.NoError(t, jobORM.CreateJob(jb)) - serviceArray, err := delegate.ServicesForSpec(testutils.Context(t), *jb) + ctx := testutils.Context(t) + require.NoError(t, jobORM.CreateJob(ctx, jb)) + serviceArray, err := delegate.ServicesForSpec(ctx, *jb) require.NoError(t, err) assert.Len(t, serviceArray, 1) service := serviceArray[0] diff --git a/core/services/feeds/mocks/orm.go b/core/services/feeds/mocks/orm.go index f84d80a6eb1..625a0b41d9a 100644 --- a/core/services/feeds/mocks/orm.go +++ b/core/services/feeds/mocks/orm.go @@ -3,10 +3,12 @@ package mocks import ( + context "context" + feeds "github.com/smartcontractkit/chainlink/v2/core/services/feeds" mock "github.com/stretchr/testify/mock" - pg "github.com/smartcontractkit/chainlink/v2/core/services/pg" + sqlutil "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" uuid "github.com/google/uuid" ) @@ -24,24 +26,17 @@ func (_m *ORM) EXPECT() *ORM_Expecter { return &ORM_Expecter{mock: &_m.Mock} } -// ApproveSpec provides a mock function with given fields: id, externalJobID, qopts -func (_m *ORM) ApproveSpec(id int64, externalJobID uuid.UUID, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id, externalJobID) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// ApproveSpec provides a mock function with given fields: ctx, id, externalJobID +func (_m *ORM) ApproveSpec(ctx context.Context, id int64, externalJobID uuid.UUID) error { + ret := _m.Called(ctx, id, externalJobID) if len(ret) == 0 { panic("no return value specified for ApproveSpec") } var r0 error - if rf, ok := ret.Get(0).(func(int64, uuid.UUID, ...pg.QOpt) error); ok { - r0 = rf(id, externalJobID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64, uuid.UUID) error); ok { + r0 = rf(ctx, id, externalJobID) } else { r0 = ret.Error(0) } @@ -55,23 +50,16 @@ type ORM_ApproveSpec_Call struct { } // ApproveSpec is a helper method to define mock.On call +// - ctx context.Context // - id int64 // - externalJobID uuid.UUID -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) ApproveSpec(id interface{}, externalJobID interface{}, qopts ...interface{}) *ORM_ApproveSpec_Call { - return &ORM_ApproveSpec_Call{Call: _e.mock.On("ApproveSpec", - append([]interface{}{id, externalJobID}, qopts...)...)} +func (_e *ORM_Expecter) ApproveSpec(ctx interface{}, id interface{}, externalJobID interface{}) *ORM_ApproveSpec_Call { + return &ORM_ApproveSpec_Call{Call: _e.mock.On("ApproveSpec", ctx, id, externalJobID)} } -func (_c *ORM_ApproveSpec_Call) Run(run func(id int64, externalJobID uuid.UUID, qopts ...pg.QOpt)) *ORM_ApproveSpec_Call { +func (_c *ORM_ApproveSpec_Call) Run(run func(ctx context.Context, id int64, externalJobID uuid.UUID)) *ORM_ApproveSpec_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), args[1].(uuid.UUID), variadicArgs...) + run(args[0].(context.Context), args[1].(int64), args[2].(uuid.UUID)) }) return _c } @@ -81,29 +69,22 @@ func (_c *ORM_ApproveSpec_Call) Return(_a0 error) *ORM_ApproveSpec_Call { return _c } -func (_c *ORM_ApproveSpec_Call) RunAndReturn(run func(int64, uuid.UUID, ...pg.QOpt) error) *ORM_ApproveSpec_Call { +func (_c *ORM_ApproveSpec_Call) RunAndReturn(run func(context.Context, int64, uuid.UUID) error) *ORM_ApproveSpec_Call { _c.Call.Return(run) return _c } -// CancelSpec provides a mock function with given fields: id, qopts -func (_m *ORM) CancelSpec(id int64, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// CancelSpec provides a mock function with given fields: ctx, id +func (_m *ORM) CancelSpec(ctx context.Context, id int64) error { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for CancelSpec") } var r0 error - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) error); ok { - r0 = rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok { + r0 = rf(ctx, id) } else { r0 = ret.Error(0) } @@ -117,22 +98,15 @@ type ORM_CancelSpec_Call struct { } // CancelSpec is a helper method to define mock.On call +// - ctx context.Context // - id int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) CancelSpec(id interface{}, qopts ...interface{}) *ORM_CancelSpec_Call { - return &ORM_CancelSpec_Call{Call: _e.mock.On("CancelSpec", - append([]interface{}{id}, qopts...)...)} +func (_e *ORM_Expecter) CancelSpec(ctx interface{}, id interface{}) *ORM_CancelSpec_Call { + return &ORM_CancelSpec_Call{Call: _e.mock.On("CancelSpec", ctx, id)} } -func (_c *ORM_CancelSpec_Call) Run(run func(id int64, qopts ...pg.QOpt)) *ORM_CancelSpec_Call { +func (_c *ORM_CancelSpec_Call) Run(run func(ctx context.Context, id int64)) *ORM_CancelSpec_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), variadicArgs...) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -142,14 +116,14 @@ func (_c *ORM_CancelSpec_Call) Return(_a0 error) *ORM_CancelSpec_Call { return _c } -func (_c *ORM_CancelSpec_Call) RunAndReturn(run func(int64, ...pg.QOpt) error) *ORM_CancelSpec_Call { +func (_c *ORM_CancelSpec_Call) RunAndReturn(run func(context.Context, int64) error) *ORM_CancelSpec_Call { _c.Call.Return(run) return _c } -// CountJobProposals provides a mock function with given fields: -func (_m *ORM) CountJobProposals() (int64, error) { - ret := _m.Called() +// CountJobProposals provides a mock function with given fields: ctx +func (_m *ORM) CountJobProposals(ctx context.Context) (int64, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for CountJobProposals") @@ -157,17 +131,17 @@ func (_m *ORM) CountJobProposals() (int64, error) { var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func() (int64, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (int64, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() int64); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) int64); ok { + r0 = rf(ctx) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -181,13 +155,14 @@ type ORM_CountJobProposals_Call struct { } // CountJobProposals is a helper method to define mock.On call -func (_e *ORM_Expecter) CountJobProposals() *ORM_CountJobProposals_Call { - return &ORM_CountJobProposals_Call{Call: _e.mock.On("CountJobProposals")} +// - ctx context.Context +func (_e *ORM_Expecter) CountJobProposals(ctx interface{}) *ORM_CountJobProposals_Call { + return &ORM_CountJobProposals_Call{Call: _e.mock.On("CountJobProposals", ctx)} } -func (_c *ORM_CountJobProposals_Call) Run(run func()) *ORM_CountJobProposals_Call { +func (_c *ORM_CountJobProposals_Call) Run(run func(ctx context.Context)) *ORM_CountJobProposals_Call { _c.Call.Run(func(args mock.Arguments) { - run() + run(args[0].(context.Context)) }) return _c } @@ -197,14 +172,14 @@ func (_c *ORM_CountJobProposals_Call) Return(_a0 int64, _a1 error) *ORM_CountJob return _c } -func (_c *ORM_CountJobProposals_Call) RunAndReturn(run func() (int64, error)) *ORM_CountJobProposals_Call { +func (_c *ORM_CountJobProposals_Call) RunAndReturn(run func(context.Context) (int64, error)) *ORM_CountJobProposals_Call { _c.Call.Return(run) return _c } -// CountJobProposalsByStatus provides a mock function with given fields: -func (_m *ORM) CountJobProposalsByStatus() (*feeds.JobProposalCounts, error) { - ret := _m.Called() +// CountJobProposalsByStatus provides a mock function with given fields: ctx +func (_m *ORM) CountJobProposalsByStatus(ctx context.Context) (*feeds.JobProposalCounts, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for CountJobProposalsByStatus") @@ -212,19 +187,19 @@ func (_m *ORM) CountJobProposalsByStatus() (*feeds.JobProposalCounts, error) { var r0 *feeds.JobProposalCounts var r1 error - if rf, ok := ret.Get(0).(func() (*feeds.JobProposalCounts, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (*feeds.JobProposalCounts, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() *feeds.JobProposalCounts); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) *feeds.JobProposalCounts); ok { + r0 = rf(ctx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.JobProposalCounts) } } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -238,13 +213,14 @@ type ORM_CountJobProposalsByStatus_Call struct { } // CountJobProposalsByStatus is a helper method to define mock.On call -func (_e *ORM_Expecter) CountJobProposalsByStatus() *ORM_CountJobProposalsByStatus_Call { - return &ORM_CountJobProposalsByStatus_Call{Call: _e.mock.On("CountJobProposalsByStatus")} +// - ctx context.Context +func (_e *ORM_Expecter) CountJobProposalsByStatus(ctx interface{}) *ORM_CountJobProposalsByStatus_Call { + return &ORM_CountJobProposalsByStatus_Call{Call: _e.mock.On("CountJobProposalsByStatus", ctx)} } -func (_c *ORM_CountJobProposalsByStatus_Call) Run(run func()) *ORM_CountJobProposalsByStatus_Call { +func (_c *ORM_CountJobProposalsByStatus_Call) Run(run func(ctx context.Context)) *ORM_CountJobProposalsByStatus_Call { _c.Call.Run(func(args mock.Arguments) { - run() + run(args[0].(context.Context)) }) return _c } @@ -254,14 +230,14 @@ func (_c *ORM_CountJobProposalsByStatus_Call) Return(counts *feeds.JobProposalCo return _c } -func (_c *ORM_CountJobProposalsByStatus_Call) RunAndReturn(run func() (*feeds.JobProposalCounts, error)) *ORM_CountJobProposalsByStatus_Call { +func (_c *ORM_CountJobProposalsByStatus_Call) RunAndReturn(run func(context.Context) (*feeds.JobProposalCounts, error)) *ORM_CountJobProposalsByStatus_Call { _c.Call.Return(run) return _c } -// CountManagers provides a mock function with given fields: -func (_m *ORM) CountManagers() (int64, error) { - ret := _m.Called() +// CountManagers provides a mock function with given fields: ctx +func (_m *ORM) CountManagers(ctx context.Context) (int64, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for CountManagers") @@ -269,17 +245,17 @@ func (_m *ORM) CountManagers() (int64, error) { var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func() (int64, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (int64, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() int64); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) int64); ok { + r0 = rf(ctx) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -293,13 +269,14 @@ type ORM_CountManagers_Call struct { } // CountManagers is a helper method to define mock.On call -func (_e *ORM_Expecter) CountManagers() *ORM_CountManagers_Call { - return &ORM_CountManagers_Call{Call: _e.mock.On("CountManagers")} +// - ctx context.Context +func (_e *ORM_Expecter) CountManagers(ctx interface{}) *ORM_CountManagers_Call { + return &ORM_CountManagers_Call{Call: _e.mock.On("CountManagers", ctx)} } -func (_c *ORM_CountManagers_Call) Run(run func()) *ORM_CountManagers_Call { +func (_c *ORM_CountManagers_Call) Run(run func(ctx context.Context)) *ORM_CountManagers_Call { _c.Call.Run(func(args mock.Arguments) { - run() + run(args[0].(context.Context)) }) return _c } @@ -309,21 +286,14 @@ func (_c *ORM_CountManagers_Call) Return(_a0 int64, _a1 error) *ORM_CountManager return _c } -func (_c *ORM_CountManagers_Call) RunAndReturn(run func() (int64, error)) *ORM_CountManagers_Call { +func (_c *ORM_CountManagers_Call) RunAndReturn(run func(context.Context) (int64, error)) *ORM_CountManagers_Call { _c.Call.Return(run) return _c } -// CreateBatchChainConfig provides a mock function with given fields: cfgs, qopts -func (_m *ORM) CreateBatchChainConfig(cfgs []feeds.ChainConfig, qopts ...pg.QOpt) ([]int64, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, cfgs) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// CreateBatchChainConfig provides a mock function with given fields: ctx, cfgs +func (_m *ORM) CreateBatchChainConfig(ctx context.Context, cfgs []feeds.ChainConfig) ([]int64, error) { + ret := _m.Called(ctx, cfgs) if len(ret) == 0 { panic("no return value specified for CreateBatchChainConfig") @@ -331,19 +301,19 @@ func (_m *ORM) CreateBatchChainConfig(cfgs []feeds.ChainConfig, qopts ...pg.QOpt var r0 []int64 var r1 error - if rf, ok := ret.Get(0).(func([]feeds.ChainConfig, ...pg.QOpt) ([]int64, error)); ok { - return rf(cfgs, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, []feeds.ChainConfig) ([]int64, error)); ok { + return rf(ctx, cfgs) } - if rf, ok := ret.Get(0).(func([]feeds.ChainConfig, ...pg.QOpt) []int64); ok { - r0 = rf(cfgs, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, []feeds.ChainConfig) []int64); ok { + r0 = rf(ctx, cfgs) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]int64) } } - if rf, ok := ret.Get(1).(func([]feeds.ChainConfig, ...pg.QOpt) error); ok { - r1 = rf(cfgs, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, []feeds.ChainConfig) error); ok { + r1 = rf(ctx, cfgs) } else { r1 = ret.Error(1) } @@ -357,22 +327,15 @@ type ORM_CreateBatchChainConfig_Call struct { } // CreateBatchChainConfig is a helper method to define mock.On call +// - ctx context.Context // - cfgs []feeds.ChainConfig -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) CreateBatchChainConfig(cfgs interface{}, qopts ...interface{}) *ORM_CreateBatchChainConfig_Call { - return &ORM_CreateBatchChainConfig_Call{Call: _e.mock.On("CreateBatchChainConfig", - append([]interface{}{cfgs}, qopts...)...)} +func (_e *ORM_Expecter) CreateBatchChainConfig(ctx interface{}, cfgs interface{}) *ORM_CreateBatchChainConfig_Call { + return &ORM_CreateBatchChainConfig_Call{Call: _e.mock.On("CreateBatchChainConfig", ctx, cfgs)} } -func (_c *ORM_CreateBatchChainConfig_Call) Run(run func(cfgs []feeds.ChainConfig, qopts ...pg.QOpt)) *ORM_CreateBatchChainConfig_Call { +func (_c *ORM_CreateBatchChainConfig_Call) Run(run func(ctx context.Context, cfgs []feeds.ChainConfig)) *ORM_CreateBatchChainConfig_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].([]feeds.ChainConfig), variadicArgs...) + run(args[0].(context.Context), args[1].([]feeds.ChainConfig)) }) return _c } @@ -382,21 +345,14 @@ func (_c *ORM_CreateBatchChainConfig_Call) Return(_a0 []int64, _a1 error) *ORM_C return _c } -func (_c *ORM_CreateBatchChainConfig_Call) RunAndReturn(run func([]feeds.ChainConfig, ...pg.QOpt) ([]int64, error)) *ORM_CreateBatchChainConfig_Call { +func (_c *ORM_CreateBatchChainConfig_Call) RunAndReturn(run func(context.Context, []feeds.ChainConfig) ([]int64, error)) *ORM_CreateBatchChainConfig_Call { _c.Call.Return(run) return _c } -// CreateChainConfig provides a mock function with given fields: cfg, qopts -func (_m *ORM) CreateChainConfig(cfg feeds.ChainConfig, qopts ...pg.QOpt) (int64, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, cfg) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// CreateChainConfig provides a mock function with given fields: ctx, cfg +func (_m *ORM) CreateChainConfig(ctx context.Context, cfg feeds.ChainConfig) (int64, error) { + ret := _m.Called(ctx, cfg) if len(ret) == 0 { panic("no return value specified for CreateChainConfig") @@ -404,17 +360,17 @@ func (_m *ORM) CreateChainConfig(cfg feeds.ChainConfig, qopts ...pg.QOpt) (int64 var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func(feeds.ChainConfig, ...pg.QOpt) (int64, error)); ok { - return rf(cfg, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, feeds.ChainConfig) (int64, error)); ok { + return rf(ctx, cfg) } - if rf, ok := ret.Get(0).(func(feeds.ChainConfig, ...pg.QOpt) int64); ok { - r0 = rf(cfg, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, feeds.ChainConfig) int64); ok { + r0 = rf(ctx, cfg) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func(feeds.ChainConfig, ...pg.QOpt) error); ok { - r1 = rf(cfg, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, feeds.ChainConfig) error); ok { + r1 = rf(ctx, cfg) } else { r1 = ret.Error(1) } @@ -428,22 +384,15 @@ type ORM_CreateChainConfig_Call struct { } // CreateChainConfig is a helper method to define mock.On call +// - ctx context.Context // - cfg feeds.ChainConfig -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) CreateChainConfig(cfg interface{}, qopts ...interface{}) *ORM_CreateChainConfig_Call { - return &ORM_CreateChainConfig_Call{Call: _e.mock.On("CreateChainConfig", - append([]interface{}{cfg}, qopts...)...)} +func (_e *ORM_Expecter) CreateChainConfig(ctx interface{}, cfg interface{}) *ORM_CreateChainConfig_Call { + return &ORM_CreateChainConfig_Call{Call: _e.mock.On("CreateChainConfig", ctx, cfg)} } -func (_c *ORM_CreateChainConfig_Call) Run(run func(cfg feeds.ChainConfig, qopts ...pg.QOpt)) *ORM_CreateChainConfig_Call { +func (_c *ORM_CreateChainConfig_Call) Run(run func(ctx context.Context, cfg feeds.ChainConfig)) *ORM_CreateChainConfig_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(feeds.ChainConfig), variadicArgs...) + run(args[0].(context.Context), args[1].(feeds.ChainConfig)) }) return _c } @@ -453,14 +402,14 @@ func (_c *ORM_CreateChainConfig_Call) Return(_a0 int64, _a1 error) *ORM_CreateCh return _c } -func (_c *ORM_CreateChainConfig_Call) RunAndReturn(run func(feeds.ChainConfig, ...pg.QOpt) (int64, error)) *ORM_CreateChainConfig_Call { +func (_c *ORM_CreateChainConfig_Call) RunAndReturn(run func(context.Context, feeds.ChainConfig) (int64, error)) *ORM_CreateChainConfig_Call { _c.Call.Return(run) return _c } -// CreateJobProposal provides a mock function with given fields: jp -func (_m *ORM) CreateJobProposal(jp *feeds.JobProposal) (int64, error) { - ret := _m.Called(jp) +// CreateJobProposal provides a mock function with given fields: ctx, jp +func (_m *ORM) CreateJobProposal(ctx context.Context, jp *feeds.JobProposal) (int64, error) { + ret := _m.Called(ctx, jp) if len(ret) == 0 { panic("no return value specified for CreateJobProposal") @@ -468,17 +417,17 @@ func (_m *ORM) CreateJobProposal(jp *feeds.JobProposal) (int64, error) { var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func(*feeds.JobProposal) (int64, error)); ok { - return rf(jp) + if rf, ok := ret.Get(0).(func(context.Context, *feeds.JobProposal) (int64, error)); ok { + return rf(ctx, jp) } - if rf, ok := ret.Get(0).(func(*feeds.JobProposal) int64); ok { - r0 = rf(jp) + if rf, ok := ret.Get(0).(func(context.Context, *feeds.JobProposal) int64); ok { + r0 = rf(ctx, jp) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func(*feeds.JobProposal) error); ok { - r1 = rf(jp) + if rf, ok := ret.Get(1).(func(context.Context, *feeds.JobProposal) error); ok { + r1 = rf(ctx, jp) } else { r1 = ret.Error(1) } @@ -492,14 +441,15 @@ type ORM_CreateJobProposal_Call struct { } // CreateJobProposal is a helper method to define mock.On call +// - ctx context.Context // - jp *feeds.JobProposal -func (_e *ORM_Expecter) CreateJobProposal(jp interface{}) *ORM_CreateJobProposal_Call { - return &ORM_CreateJobProposal_Call{Call: _e.mock.On("CreateJobProposal", jp)} +func (_e *ORM_Expecter) CreateJobProposal(ctx interface{}, jp interface{}) *ORM_CreateJobProposal_Call { + return &ORM_CreateJobProposal_Call{Call: _e.mock.On("CreateJobProposal", ctx, jp)} } -func (_c *ORM_CreateJobProposal_Call) Run(run func(jp *feeds.JobProposal)) *ORM_CreateJobProposal_Call { +func (_c *ORM_CreateJobProposal_Call) Run(run func(ctx context.Context, jp *feeds.JobProposal)) *ORM_CreateJobProposal_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*feeds.JobProposal)) + run(args[0].(context.Context), args[1].(*feeds.JobProposal)) }) return _c } @@ -509,21 +459,14 @@ func (_c *ORM_CreateJobProposal_Call) Return(_a0 int64, _a1 error) *ORM_CreateJo return _c } -func (_c *ORM_CreateJobProposal_Call) RunAndReturn(run func(*feeds.JobProposal) (int64, error)) *ORM_CreateJobProposal_Call { +func (_c *ORM_CreateJobProposal_Call) RunAndReturn(run func(context.Context, *feeds.JobProposal) (int64, error)) *ORM_CreateJobProposal_Call { _c.Call.Return(run) return _c } -// CreateManager provides a mock function with given fields: ms, qopts -func (_m *ORM) CreateManager(ms *feeds.FeedsManager, qopts ...pg.QOpt) (int64, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, ms) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// CreateManager provides a mock function with given fields: ctx, ms +func (_m *ORM) CreateManager(ctx context.Context, ms *feeds.FeedsManager) (int64, error) { + ret := _m.Called(ctx, ms) if len(ret) == 0 { panic("no return value specified for CreateManager") @@ -531,17 +474,17 @@ func (_m *ORM) CreateManager(ms *feeds.FeedsManager, qopts ...pg.QOpt) (int64, e var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func(*feeds.FeedsManager, ...pg.QOpt) (int64, error)); ok { - return rf(ms, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, *feeds.FeedsManager) (int64, error)); ok { + return rf(ctx, ms) } - if rf, ok := ret.Get(0).(func(*feeds.FeedsManager, ...pg.QOpt) int64); ok { - r0 = rf(ms, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, *feeds.FeedsManager) int64); ok { + r0 = rf(ctx, ms) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func(*feeds.FeedsManager, ...pg.QOpt) error); ok { - r1 = rf(ms, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, *feeds.FeedsManager) error); ok { + r1 = rf(ctx, ms) } else { r1 = ret.Error(1) } @@ -555,22 +498,15 @@ type ORM_CreateManager_Call struct { } // CreateManager is a helper method to define mock.On call +// - ctx context.Context // - ms *feeds.FeedsManager -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) CreateManager(ms interface{}, qopts ...interface{}) *ORM_CreateManager_Call { - return &ORM_CreateManager_Call{Call: _e.mock.On("CreateManager", - append([]interface{}{ms}, qopts...)...)} +func (_e *ORM_Expecter) CreateManager(ctx interface{}, ms interface{}) *ORM_CreateManager_Call { + return &ORM_CreateManager_Call{Call: _e.mock.On("CreateManager", ctx, ms)} } -func (_c *ORM_CreateManager_Call) Run(run func(ms *feeds.FeedsManager, qopts ...pg.QOpt)) *ORM_CreateManager_Call { +func (_c *ORM_CreateManager_Call) Run(run func(ctx context.Context, ms *feeds.FeedsManager)) *ORM_CreateManager_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(*feeds.FeedsManager), variadicArgs...) + run(args[0].(context.Context), args[1].(*feeds.FeedsManager)) }) return _c } @@ -580,21 +516,14 @@ func (_c *ORM_CreateManager_Call) Return(_a0 int64, _a1 error) *ORM_CreateManage return _c } -func (_c *ORM_CreateManager_Call) RunAndReturn(run func(*feeds.FeedsManager, ...pg.QOpt) (int64, error)) *ORM_CreateManager_Call { +func (_c *ORM_CreateManager_Call) RunAndReturn(run func(context.Context, *feeds.FeedsManager) (int64, error)) *ORM_CreateManager_Call { _c.Call.Return(run) return _c } -// CreateSpec provides a mock function with given fields: spec, qopts -func (_m *ORM) CreateSpec(spec feeds.JobProposalSpec, qopts ...pg.QOpt) (int64, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, spec) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// CreateSpec provides a mock function with given fields: ctx, spec +func (_m *ORM) CreateSpec(ctx context.Context, spec feeds.JobProposalSpec) (int64, error) { + ret := _m.Called(ctx, spec) if len(ret) == 0 { panic("no return value specified for CreateSpec") @@ -602,17 +531,17 @@ func (_m *ORM) CreateSpec(spec feeds.JobProposalSpec, qopts ...pg.QOpt) (int64, var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func(feeds.JobProposalSpec, ...pg.QOpt) (int64, error)); ok { - return rf(spec, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, feeds.JobProposalSpec) (int64, error)); ok { + return rf(ctx, spec) } - if rf, ok := ret.Get(0).(func(feeds.JobProposalSpec, ...pg.QOpt) int64); ok { - r0 = rf(spec, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, feeds.JobProposalSpec) int64); ok { + r0 = rf(ctx, spec) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func(feeds.JobProposalSpec, ...pg.QOpt) error); ok { - r1 = rf(spec, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, feeds.JobProposalSpec) error); ok { + r1 = rf(ctx, spec) } else { r1 = ret.Error(1) } @@ -626,22 +555,15 @@ type ORM_CreateSpec_Call struct { } // CreateSpec is a helper method to define mock.On call +// - ctx context.Context // - spec feeds.JobProposalSpec -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) CreateSpec(spec interface{}, qopts ...interface{}) *ORM_CreateSpec_Call { - return &ORM_CreateSpec_Call{Call: _e.mock.On("CreateSpec", - append([]interface{}{spec}, qopts...)...)} +func (_e *ORM_Expecter) CreateSpec(ctx interface{}, spec interface{}) *ORM_CreateSpec_Call { + return &ORM_CreateSpec_Call{Call: _e.mock.On("CreateSpec", ctx, spec)} } -func (_c *ORM_CreateSpec_Call) Run(run func(spec feeds.JobProposalSpec, qopts ...pg.QOpt)) *ORM_CreateSpec_Call { +func (_c *ORM_CreateSpec_Call) Run(run func(ctx context.Context, spec feeds.JobProposalSpec)) *ORM_CreateSpec_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(feeds.JobProposalSpec), variadicArgs...) + run(args[0].(context.Context), args[1].(feeds.JobProposalSpec)) }) return _c } @@ -651,14 +573,14 @@ func (_c *ORM_CreateSpec_Call) Return(_a0 int64, _a1 error) *ORM_CreateSpec_Call return _c } -func (_c *ORM_CreateSpec_Call) RunAndReturn(run func(feeds.JobProposalSpec, ...pg.QOpt) (int64, error)) *ORM_CreateSpec_Call { +func (_c *ORM_CreateSpec_Call) RunAndReturn(run func(context.Context, feeds.JobProposalSpec) (int64, error)) *ORM_CreateSpec_Call { _c.Call.Return(run) return _c } -// DeleteChainConfig provides a mock function with given fields: id -func (_m *ORM) DeleteChainConfig(id int64) (int64, error) { - ret := _m.Called(id) +// DeleteChainConfig provides a mock function with given fields: ctx, id +func (_m *ORM) DeleteChainConfig(ctx context.Context, id int64) (int64, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for DeleteChainConfig") @@ -666,17 +588,17 @@ func (_m *ORM) DeleteChainConfig(id int64) (int64, error) { var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func(int64) (int64, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) (int64, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64) int64); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) int64); ok { + r0 = rf(ctx, id) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -690,14 +612,15 @@ type ORM_DeleteChainConfig_Call struct { } // DeleteChainConfig is a helper method to define mock.On call +// - ctx context.Context // - id int64 -func (_e *ORM_Expecter) DeleteChainConfig(id interface{}) *ORM_DeleteChainConfig_Call { - return &ORM_DeleteChainConfig_Call{Call: _e.mock.On("DeleteChainConfig", id)} +func (_e *ORM_Expecter) DeleteChainConfig(ctx interface{}, id interface{}) *ORM_DeleteChainConfig_Call { + return &ORM_DeleteChainConfig_Call{Call: _e.mock.On("DeleteChainConfig", ctx, id)} } -func (_c *ORM_DeleteChainConfig_Call) Run(run func(id int64)) *ORM_DeleteChainConfig_Call { +func (_c *ORM_DeleteChainConfig_Call) Run(run func(ctx context.Context, id int64)) *ORM_DeleteChainConfig_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(int64)) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -707,29 +630,22 @@ func (_c *ORM_DeleteChainConfig_Call) Return(_a0 int64, _a1 error) *ORM_DeleteCh return _c } -func (_c *ORM_DeleteChainConfig_Call) RunAndReturn(run func(int64) (int64, error)) *ORM_DeleteChainConfig_Call { +func (_c *ORM_DeleteChainConfig_Call) RunAndReturn(run func(context.Context, int64) (int64, error)) *ORM_DeleteChainConfig_Call { _c.Call.Return(run) return _c } -// DeleteProposal provides a mock function with given fields: id, qopts -func (_m *ORM) DeleteProposal(id int64, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// DeleteProposal provides a mock function with given fields: ctx, id +func (_m *ORM) DeleteProposal(ctx context.Context, id int64) error { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for DeleteProposal") } var r0 error - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) error); ok { - r0 = rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok { + r0 = rf(ctx, id) } else { r0 = ret.Error(0) } @@ -743,22 +659,15 @@ type ORM_DeleteProposal_Call struct { } // DeleteProposal is a helper method to define mock.On call +// - ctx context.Context // - id int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) DeleteProposal(id interface{}, qopts ...interface{}) *ORM_DeleteProposal_Call { - return &ORM_DeleteProposal_Call{Call: _e.mock.On("DeleteProposal", - append([]interface{}{id}, qopts...)...)} +func (_e *ORM_Expecter) DeleteProposal(ctx interface{}, id interface{}) *ORM_DeleteProposal_Call { + return &ORM_DeleteProposal_Call{Call: _e.mock.On("DeleteProposal", ctx, id)} } -func (_c *ORM_DeleteProposal_Call) Run(run func(id int64, qopts ...pg.QOpt)) *ORM_DeleteProposal_Call { +func (_c *ORM_DeleteProposal_Call) Run(run func(ctx context.Context, id int64)) *ORM_DeleteProposal_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), variadicArgs...) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -768,21 +677,14 @@ func (_c *ORM_DeleteProposal_Call) Return(_a0 error) *ORM_DeleteProposal_Call { return _c } -func (_c *ORM_DeleteProposal_Call) RunAndReturn(run func(int64, ...pg.QOpt) error) *ORM_DeleteProposal_Call { +func (_c *ORM_DeleteProposal_Call) RunAndReturn(run func(context.Context, int64) error) *ORM_DeleteProposal_Call { _c.Call.Return(run) return _c } -// ExistsSpecByJobProposalIDAndVersion provides a mock function with given fields: jpID, version, qopts -func (_m *ORM) ExistsSpecByJobProposalIDAndVersion(jpID int64, version int32, qopts ...pg.QOpt) (bool, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, jpID, version) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// ExistsSpecByJobProposalIDAndVersion provides a mock function with given fields: ctx, jpID, version +func (_m *ORM) ExistsSpecByJobProposalIDAndVersion(ctx context.Context, jpID int64, version int32) (bool, error) { + ret := _m.Called(ctx, jpID, version) if len(ret) == 0 { panic("no return value specified for ExistsSpecByJobProposalIDAndVersion") @@ -790,17 +692,17 @@ func (_m *ORM) ExistsSpecByJobProposalIDAndVersion(jpID int64, version int32, qo var r0 bool var r1 error - if rf, ok := ret.Get(0).(func(int64, int32, ...pg.QOpt) (bool, error)); ok { - return rf(jpID, version, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64, int32) (bool, error)); ok { + return rf(ctx, jpID, version) } - if rf, ok := ret.Get(0).(func(int64, int32, ...pg.QOpt) bool); ok { - r0 = rf(jpID, version, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64, int32) bool); ok { + r0 = rf(ctx, jpID, version) } else { r0 = ret.Get(0).(bool) } - if rf, ok := ret.Get(1).(func(int64, int32, ...pg.QOpt) error); ok { - r1 = rf(jpID, version, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, int64, int32) error); ok { + r1 = rf(ctx, jpID, version) } else { r1 = ret.Error(1) } @@ -814,23 +716,16 @@ type ORM_ExistsSpecByJobProposalIDAndVersion_Call struct { } // ExistsSpecByJobProposalIDAndVersion is a helper method to define mock.On call +// - ctx context.Context // - jpID int64 // - version int32 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) ExistsSpecByJobProposalIDAndVersion(jpID interface{}, version interface{}, qopts ...interface{}) *ORM_ExistsSpecByJobProposalIDAndVersion_Call { - return &ORM_ExistsSpecByJobProposalIDAndVersion_Call{Call: _e.mock.On("ExistsSpecByJobProposalIDAndVersion", - append([]interface{}{jpID, version}, qopts...)...)} +func (_e *ORM_Expecter) ExistsSpecByJobProposalIDAndVersion(ctx interface{}, jpID interface{}, version interface{}) *ORM_ExistsSpecByJobProposalIDAndVersion_Call { + return &ORM_ExistsSpecByJobProposalIDAndVersion_Call{Call: _e.mock.On("ExistsSpecByJobProposalIDAndVersion", ctx, jpID, version)} } -func (_c *ORM_ExistsSpecByJobProposalIDAndVersion_Call) Run(run func(jpID int64, version int32, qopts ...pg.QOpt)) *ORM_ExistsSpecByJobProposalIDAndVersion_Call { +func (_c *ORM_ExistsSpecByJobProposalIDAndVersion_Call) Run(run func(ctx context.Context, jpID int64, version int32)) *ORM_ExistsSpecByJobProposalIDAndVersion_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), args[1].(int32), variadicArgs...) + run(args[0].(context.Context), args[1].(int64), args[2].(int32)) }) return _c } @@ -840,21 +735,14 @@ func (_c *ORM_ExistsSpecByJobProposalIDAndVersion_Call) Return(exists bool, err return _c } -func (_c *ORM_ExistsSpecByJobProposalIDAndVersion_Call) RunAndReturn(run func(int64, int32, ...pg.QOpt) (bool, error)) *ORM_ExistsSpecByJobProposalIDAndVersion_Call { +func (_c *ORM_ExistsSpecByJobProposalIDAndVersion_Call) RunAndReturn(run func(context.Context, int64, int32) (bool, error)) *ORM_ExistsSpecByJobProposalIDAndVersion_Call { _c.Call.Return(run) return _c } -// GetApprovedSpec provides a mock function with given fields: jpID, qopts -func (_m *ORM) GetApprovedSpec(jpID int64, qopts ...pg.QOpt) (*feeds.JobProposalSpec, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, jpID) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// GetApprovedSpec provides a mock function with given fields: ctx, jpID +func (_m *ORM) GetApprovedSpec(ctx context.Context, jpID int64) (*feeds.JobProposalSpec, error) { + ret := _m.Called(ctx, jpID) if len(ret) == 0 { panic("no return value specified for GetApprovedSpec") @@ -862,19 +750,19 @@ func (_m *ORM) GetApprovedSpec(jpID int64, qopts ...pg.QOpt) (*feeds.JobProposal var r0 *feeds.JobProposalSpec var r1 error - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) (*feeds.JobProposalSpec, error)); ok { - return rf(jpID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.JobProposalSpec, error)); ok { + return rf(ctx, jpID) } - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) *feeds.JobProposalSpec); ok { - r0 = rf(jpID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.JobProposalSpec); ok { + r0 = rf(ctx, jpID) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.JobProposalSpec) } } - if rf, ok := ret.Get(1).(func(int64, ...pg.QOpt) error); ok { - r1 = rf(jpID, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, jpID) } else { r1 = ret.Error(1) } @@ -888,22 +776,15 @@ type ORM_GetApprovedSpec_Call struct { } // GetApprovedSpec is a helper method to define mock.On call +// - ctx context.Context // - jpID int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) GetApprovedSpec(jpID interface{}, qopts ...interface{}) *ORM_GetApprovedSpec_Call { - return &ORM_GetApprovedSpec_Call{Call: _e.mock.On("GetApprovedSpec", - append([]interface{}{jpID}, qopts...)...)} +func (_e *ORM_Expecter) GetApprovedSpec(ctx interface{}, jpID interface{}) *ORM_GetApprovedSpec_Call { + return &ORM_GetApprovedSpec_Call{Call: _e.mock.On("GetApprovedSpec", ctx, jpID)} } -func (_c *ORM_GetApprovedSpec_Call) Run(run func(jpID int64, qopts ...pg.QOpt)) *ORM_GetApprovedSpec_Call { +func (_c *ORM_GetApprovedSpec_Call) Run(run func(ctx context.Context, jpID int64)) *ORM_GetApprovedSpec_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), variadicArgs...) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -913,14 +794,14 @@ func (_c *ORM_GetApprovedSpec_Call) Return(_a0 *feeds.JobProposalSpec, _a1 error return _c } -func (_c *ORM_GetApprovedSpec_Call) RunAndReturn(run func(int64, ...pg.QOpt) (*feeds.JobProposalSpec, error)) *ORM_GetApprovedSpec_Call { +func (_c *ORM_GetApprovedSpec_Call) RunAndReturn(run func(context.Context, int64) (*feeds.JobProposalSpec, error)) *ORM_GetApprovedSpec_Call { _c.Call.Return(run) return _c } -// GetChainConfig provides a mock function with given fields: id -func (_m *ORM) GetChainConfig(id int64) (*feeds.ChainConfig, error) { - ret := _m.Called(id) +// GetChainConfig provides a mock function with given fields: ctx, id +func (_m *ORM) GetChainConfig(ctx context.Context, id int64) (*feeds.ChainConfig, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for GetChainConfig") @@ -928,19 +809,19 @@ func (_m *ORM) GetChainConfig(id int64) (*feeds.ChainConfig, error) { var r0 *feeds.ChainConfig var r1 error - if rf, ok := ret.Get(0).(func(int64) (*feeds.ChainConfig, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.ChainConfig, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64) *feeds.ChainConfig); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.ChainConfig); ok { + r0 = rf(ctx, id) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.ChainConfig) } } - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -954,14 +835,15 @@ type ORM_GetChainConfig_Call struct { } // GetChainConfig is a helper method to define mock.On call +// - ctx context.Context // - id int64 -func (_e *ORM_Expecter) GetChainConfig(id interface{}) *ORM_GetChainConfig_Call { - return &ORM_GetChainConfig_Call{Call: _e.mock.On("GetChainConfig", id)} +func (_e *ORM_Expecter) GetChainConfig(ctx interface{}, id interface{}) *ORM_GetChainConfig_Call { + return &ORM_GetChainConfig_Call{Call: _e.mock.On("GetChainConfig", ctx, id)} } -func (_c *ORM_GetChainConfig_Call) Run(run func(id int64)) *ORM_GetChainConfig_Call { +func (_c *ORM_GetChainConfig_Call) Run(run func(ctx context.Context, id int64)) *ORM_GetChainConfig_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(int64)) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -971,21 +853,14 @@ func (_c *ORM_GetChainConfig_Call) Return(_a0 *feeds.ChainConfig, _a1 error) *OR return _c } -func (_c *ORM_GetChainConfig_Call) RunAndReturn(run func(int64) (*feeds.ChainConfig, error)) *ORM_GetChainConfig_Call { +func (_c *ORM_GetChainConfig_Call) RunAndReturn(run func(context.Context, int64) (*feeds.ChainConfig, error)) *ORM_GetChainConfig_Call { _c.Call.Return(run) return _c } -// GetJobProposal provides a mock function with given fields: id, qopts -func (_m *ORM) GetJobProposal(id int64, qopts ...pg.QOpt) (*feeds.JobProposal, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// GetJobProposal provides a mock function with given fields: ctx, id +func (_m *ORM) GetJobProposal(ctx context.Context, id int64) (*feeds.JobProposal, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for GetJobProposal") @@ -993,19 +868,19 @@ func (_m *ORM) GetJobProposal(id int64, qopts ...pg.QOpt) (*feeds.JobProposal, e var r0 *feeds.JobProposal var r1 error - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) (*feeds.JobProposal, error)); ok { - return rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.JobProposal, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) *feeds.JobProposal); ok { - r0 = rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.JobProposal); ok { + r0 = rf(ctx, id) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.JobProposal) } } - if rf, ok := ret.Get(1).(func(int64, ...pg.QOpt) error); ok { - r1 = rf(id, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -1019,22 +894,15 @@ type ORM_GetJobProposal_Call struct { } // GetJobProposal is a helper method to define mock.On call +// - ctx context.Context // - id int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) GetJobProposal(id interface{}, qopts ...interface{}) *ORM_GetJobProposal_Call { - return &ORM_GetJobProposal_Call{Call: _e.mock.On("GetJobProposal", - append([]interface{}{id}, qopts...)...)} +func (_e *ORM_Expecter) GetJobProposal(ctx interface{}, id interface{}) *ORM_GetJobProposal_Call { + return &ORM_GetJobProposal_Call{Call: _e.mock.On("GetJobProposal", ctx, id)} } -func (_c *ORM_GetJobProposal_Call) Run(run func(id int64, qopts ...pg.QOpt)) *ORM_GetJobProposal_Call { +func (_c *ORM_GetJobProposal_Call) Run(run func(ctx context.Context, id int64)) *ORM_GetJobProposal_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), variadicArgs...) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -1044,14 +912,14 @@ func (_c *ORM_GetJobProposal_Call) Return(_a0 *feeds.JobProposal, _a1 error) *OR return _c } -func (_c *ORM_GetJobProposal_Call) RunAndReturn(run func(int64, ...pg.QOpt) (*feeds.JobProposal, error)) *ORM_GetJobProposal_Call { +func (_c *ORM_GetJobProposal_Call) RunAndReturn(run func(context.Context, int64) (*feeds.JobProposal, error)) *ORM_GetJobProposal_Call { _c.Call.Return(run) return _c } -// GetJobProposalByRemoteUUID provides a mock function with given fields: _a0 -func (_m *ORM) GetJobProposalByRemoteUUID(_a0 uuid.UUID) (*feeds.JobProposal, error) { - ret := _m.Called(_a0) +// GetJobProposalByRemoteUUID provides a mock function with given fields: ctx, _a1 +func (_m *ORM) GetJobProposalByRemoteUUID(ctx context.Context, _a1 uuid.UUID) (*feeds.JobProposal, error) { + ret := _m.Called(ctx, _a1) if len(ret) == 0 { panic("no return value specified for GetJobProposalByRemoteUUID") @@ -1059,19 +927,19 @@ func (_m *ORM) GetJobProposalByRemoteUUID(_a0 uuid.UUID) (*feeds.JobProposal, er var r0 *feeds.JobProposal var r1 error - if rf, ok := ret.Get(0).(func(uuid.UUID) (*feeds.JobProposal, error)); ok { - return rf(_a0) + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID) (*feeds.JobProposal, error)); ok { + return rf(ctx, _a1) } - if rf, ok := ret.Get(0).(func(uuid.UUID) *feeds.JobProposal); ok { - r0 = rf(_a0) + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID) *feeds.JobProposal); ok { + r0 = rf(ctx, _a1) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.JobProposal) } } - if rf, ok := ret.Get(1).(func(uuid.UUID) error); ok { - r1 = rf(_a0) + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID) error); ok { + r1 = rf(ctx, _a1) } else { r1 = ret.Error(1) } @@ -1085,14 +953,15 @@ type ORM_GetJobProposalByRemoteUUID_Call struct { } // GetJobProposalByRemoteUUID is a helper method to define mock.On call -// - _a0 uuid.UUID -func (_e *ORM_Expecter) GetJobProposalByRemoteUUID(_a0 interface{}) *ORM_GetJobProposalByRemoteUUID_Call { - return &ORM_GetJobProposalByRemoteUUID_Call{Call: _e.mock.On("GetJobProposalByRemoteUUID", _a0)} +// - ctx context.Context +// - _a1 uuid.UUID +func (_e *ORM_Expecter) GetJobProposalByRemoteUUID(ctx interface{}, _a1 interface{}) *ORM_GetJobProposalByRemoteUUID_Call { + return &ORM_GetJobProposalByRemoteUUID_Call{Call: _e.mock.On("GetJobProposalByRemoteUUID", ctx, _a1)} } -func (_c *ORM_GetJobProposalByRemoteUUID_Call) Run(run func(_a0 uuid.UUID)) *ORM_GetJobProposalByRemoteUUID_Call { +func (_c *ORM_GetJobProposalByRemoteUUID_Call) Run(run func(ctx context.Context, _a1 uuid.UUID)) *ORM_GetJobProposalByRemoteUUID_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(uuid.UUID)) + run(args[0].(context.Context), args[1].(uuid.UUID)) }) return _c } @@ -1102,14 +971,14 @@ func (_c *ORM_GetJobProposalByRemoteUUID_Call) Return(_a0 *feeds.JobProposal, _a return _c } -func (_c *ORM_GetJobProposalByRemoteUUID_Call) RunAndReturn(run func(uuid.UUID) (*feeds.JobProposal, error)) *ORM_GetJobProposalByRemoteUUID_Call { +func (_c *ORM_GetJobProposalByRemoteUUID_Call) RunAndReturn(run func(context.Context, uuid.UUID) (*feeds.JobProposal, error)) *ORM_GetJobProposalByRemoteUUID_Call { _c.Call.Return(run) return _c } -// GetLatestSpec provides a mock function with given fields: jpID -func (_m *ORM) GetLatestSpec(jpID int64) (*feeds.JobProposalSpec, error) { - ret := _m.Called(jpID) +// GetLatestSpec provides a mock function with given fields: ctx, jpID +func (_m *ORM) GetLatestSpec(ctx context.Context, jpID int64) (*feeds.JobProposalSpec, error) { + ret := _m.Called(ctx, jpID) if len(ret) == 0 { panic("no return value specified for GetLatestSpec") @@ -1117,19 +986,19 @@ func (_m *ORM) GetLatestSpec(jpID int64) (*feeds.JobProposalSpec, error) { var r0 *feeds.JobProposalSpec var r1 error - if rf, ok := ret.Get(0).(func(int64) (*feeds.JobProposalSpec, error)); ok { - return rf(jpID) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.JobProposalSpec, error)); ok { + return rf(ctx, jpID) } - if rf, ok := ret.Get(0).(func(int64) *feeds.JobProposalSpec); ok { - r0 = rf(jpID) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.JobProposalSpec); ok { + r0 = rf(ctx, jpID) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.JobProposalSpec) } } - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(jpID) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, jpID) } else { r1 = ret.Error(1) } @@ -1143,14 +1012,15 @@ type ORM_GetLatestSpec_Call struct { } // GetLatestSpec is a helper method to define mock.On call +// - ctx context.Context // - jpID int64 -func (_e *ORM_Expecter) GetLatestSpec(jpID interface{}) *ORM_GetLatestSpec_Call { - return &ORM_GetLatestSpec_Call{Call: _e.mock.On("GetLatestSpec", jpID)} +func (_e *ORM_Expecter) GetLatestSpec(ctx interface{}, jpID interface{}) *ORM_GetLatestSpec_Call { + return &ORM_GetLatestSpec_Call{Call: _e.mock.On("GetLatestSpec", ctx, jpID)} } -func (_c *ORM_GetLatestSpec_Call) Run(run func(jpID int64)) *ORM_GetLatestSpec_Call { +func (_c *ORM_GetLatestSpec_Call) Run(run func(ctx context.Context, jpID int64)) *ORM_GetLatestSpec_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(int64)) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -1160,14 +1030,14 @@ func (_c *ORM_GetLatestSpec_Call) Return(_a0 *feeds.JobProposalSpec, _a1 error) return _c } -func (_c *ORM_GetLatestSpec_Call) RunAndReturn(run func(int64) (*feeds.JobProposalSpec, error)) *ORM_GetLatestSpec_Call { +func (_c *ORM_GetLatestSpec_Call) RunAndReturn(run func(context.Context, int64) (*feeds.JobProposalSpec, error)) *ORM_GetLatestSpec_Call { _c.Call.Return(run) return _c } -// GetManager provides a mock function with given fields: id -func (_m *ORM) GetManager(id int64) (*feeds.FeedsManager, error) { - ret := _m.Called(id) +// GetManager provides a mock function with given fields: ctx, id +func (_m *ORM) GetManager(ctx context.Context, id int64) (*feeds.FeedsManager, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for GetManager") @@ -1175,19 +1045,19 @@ func (_m *ORM) GetManager(id int64) (*feeds.FeedsManager, error) { var r0 *feeds.FeedsManager var r1 error - if rf, ok := ret.Get(0).(func(int64) (*feeds.FeedsManager, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.FeedsManager, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64) *feeds.FeedsManager); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.FeedsManager); ok { + r0 = rf(ctx, id) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.FeedsManager) } } - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -1201,14 +1071,15 @@ type ORM_GetManager_Call struct { } // GetManager is a helper method to define mock.On call +// - ctx context.Context // - id int64 -func (_e *ORM_Expecter) GetManager(id interface{}) *ORM_GetManager_Call { - return &ORM_GetManager_Call{Call: _e.mock.On("GetManager", id)} +func (_e *ORM_Expecter) GetManager(ctx interface{}, id interface{}) *ORM_GetManager_Call { + return &ORM_GetManager_Call{Call: _e.mock.On("GetManager", ctx, id)} } -func (_c *ORM_GetManager_Call) Run(run func(id int64)) *ORM_GetManager_Call { +func (_c *ORM_GetManager_Call) Run(run func(ctx context.Context, id int64)) *ORM_GetManager_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(int64)) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -1218,21 +1089,14 @@ func (_c *ORM_GetManager_Call) Return(_a0 *feeds.FeedsManager, _a1 error) *ORM_G return _c } -func (_c *ORM_GetManager_Call) RunAndReturn(run func(int64) (*feeds.FeedsManager, error)) *ORM_GetManager_Call { +func (_c *ORM_GetManager_Call) RunAndReturn(run func(context.Context, int64) (*feeds.FeedsManager, error)) *ORM_GetManager_Call { _c.Call.Return(run) return _c } -// GetSpec provides a mock function with given fields: id, qopts -func (_m *ORM) GetSpec(id int64, qopts ...pg.QOpt) (*feeds.JobProposalSpec, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// GetSpec provides a mock function with given fields: ctx, id +func (_m *ORM) GetSpec(ctx context.Context, id int64) (*feeds.JobProposalSpec, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for GetSpec") @@ -1240,19 +1104,19 @@ func (_m *ORM) GetSpec(id int64, qopts ...pg.QOpt) (*feeds.JobProposalSpec, erro var r0 *feeds.JobProposalSpec var r1 error - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) (*feeds.JobProposalSpec, error)); ok { - return rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.JobProposalSpec, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) *feeds.JobProposalSpec); ok { - r0 = rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.JobProposalSpec); ok { + r0 = rf(ctx, id) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.JobProposalSpec) } } - if rf, ok := ret.Get(1).(func(int64, ...pg.QOpt) error); ok { - r1 = rf(id, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -1266,22 +1130,15 @@ type ORM_GetSpec_Call struct { } // GetSpec is a helper method to define mock.On call +// - ctx context.Context // - id int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) GetSpec(id interface{}, qopts ...interface{}) *ORM_GetSpec_Call { - return &ORM_GetSpec_Call{Call: _e.mock.On("GetSpec", - append([]interface{}{id}, qopts...)...)} +func (_e *ORM_Expecter) GetSpec(ctx interface{}, id interface{}) *ORM_GetSpec_Call { + return &ORM_GetSpec_Call{Call: _e.mock.On("GetSpec", ctx, id)} } -func (_c *ORM_GetSpec_Call) Run(run func(id int64, qopts ...pg.QOpt)) *ORM_GetSpec_Call { +func (_c *ORM_GetSpec_Call) Run(run func(ctx context.Context, id int64)) *ORM_GetSpec_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), variadicArgs...) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -1291,21 +1148,14 @@ func (_c *ORM_GetSpec_Call) Return(_a0 *feeds.JobProposalSpec, _a1 error) *ORM_G return _c } -func (_c *ORM_GetSpec_Call) RunAndReturn(run func(int64, ...pg.QOpt) (*feeds.JobProposalSpec, error)) *ORM_GetSpec_Call { +func (_c *ORM_GetSpec_Call) RunAndReturn(run func(context.Context, int64) (*feeds.JobProposalSpec, error)) *ORM_GetSpec_Call { _c.Call.Return(run) return _c } -// IsJobManaged provides a mock function with given fields: jobID, qopts -func (_m *ORM) IsJobManaged(jobID int64, qopts ...pg.QOpt) (bool, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, jobID) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// IsJobManaged provides a mock function with given fields: ctx, jobID +func (_m *ORM) IsJobManaged(ctx context.Context, jobID int64) (bool, error) { + ret := _m.Called(ctx, jobID) if len(ret) == 0 { panic("no return value specified for IsJobManaged") @@ -1313,17 +1163,17 @@ func (_m *ORM) IsJobManaged(jobID int64, qopts ...pg.QOpt) (bool, error) { var r0 bool var r1 error - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) (bool, error)); ok { - return rf(jobID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) (bool, error)); ok { + return rf(ctx, jobID) } - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) bool); ok { - r0 = rf(jobID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) bool); ok { + r0 = rf(ctx, jobID) } else { r0 = ret.Get(0).(bool) } - if rf, ok := ret.Get(1).(func(int64, ...pg.QOpt) error); ok { - r1 = rf(jobID, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, jobID) } else { r1 = ret.Error(1) } @@ -1337,22 +1187,15 @@ type ORM_IsJobManaged_Call struct { } // IsJobManaged is a helper method to define mock.On call +// - ctx context.Context // - jobID int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) IsJobManaged(jobID interface{}, qopts ...interface{}) *ORM_IsJobManaged_Call { - return &ORM_IsJobManaged_Call{Call: _e.mock.On("IsJobManaged", - append([]interface{}{jobID}, qopts...)...)} +func (_e *ORM_Expecter) IsJobManaged(ctx interface{}, jobID interface{}) *ORM_IsJobManaged_Call { + return &ORM_IsJobManaged_Call{Call: _e.mock.On("IsJobManaged", ctx, jobID)} } -func (_c *ORM_IsJobManaged_Call) Run(run func(jobID int64, qopts ...pg.QOpt)) *ORM_IsJobManaged_Call { +func (_c *ORM_IsJobManaged_Call) Run(run func(ctx context.Context, jobID int64)) *ORM_IsJobManaged_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), variadicArgs...) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -1362,14 +1205,14 @@ func (_c *ORM_IsJobManaged_Call) Return(_a0 bool, _a1 error) *ORM_IsJobManaged_C return _c } -func (_c *ORM_IsJobManaged_Call) RunAndReturn(run func(int64, ...pg.QOpt) (bool, error)) *ORM_IsJobManaged_Call { +func (_c *ORM_IsJobManaged_Call) RunAndReturn(run func(context.Context, int64) (bool, error)) *ORM_IsJobManaged_Call { _c.Call.Return(run) return _c } -// ListChainConfigsByManagerIDs provides a mock function with given fields: mgrIDs -func (_m *ORM) ListChainConfigsByManagerIDs(mgrIDs []int64) ([]feeds.ChainConfig, error) { - ret := _m.Called(mgrIDs) +// ListChainConfigsByManagerIDs provides a mock function with given fields: ctx, mgrIDs +func (_m *ORM) ListChainConfigsByManagerIDs(ctx context.Context, mgrIDs []int64) ([]feeds.ChainConfig, error) { + ret := _m.Called(ctx, mgrIDs) if len(ret) == 0 { panic("no return value specified for ListChainConfigsByManagerIDs") @@ -1377,19 +1220,19 @@ func (_m *ORM) ListChainConfigsByManagerIDs(mgrIDs []int64) ([]feeds.ChainConfig var r0 []feeds.ChainConfig var r1 error - if rf, ok := ret.Get(0).(func([]int64) ([]feeds.ChainConfig, error)); ok { - return rf(mgrIDs) + if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]feeds.ChainConfig, error)); ok { + return rf(ctx, mgrIDs) } - if rf, ok := ret.Get(0).(func([]int64) []feeds.ChainConfig); ok { - r0 = rf(mgrIDs) + if rf, ok := ret.Get(0).(func(context.Context, []int64) []feeds.ChainConfig); ok { + r0 = rf(ctx, mgrIDs) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.ChainConfig) } } - if rf, ok := ret.Get(1).(func([]int64) error); ok { - r1 = rf(mgrIDs) + if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok { + r1 = rf(ctx, mgrIDs) } else { r1 = ret.Error(1) } @@ -1403,14 +1246,15 @@ type ORM_ListChainConfigsByManagerIDs_Call struct { } // ListChainConfigsByManagerIDs is a helper method to define mock.On call +// - ctx context.Context // - mgrIDs []int64 -func (_e *ORM_Expecter) ListChainConfigsByManagerIDs(mgrIDs interface{}) *ORM_ListChainConfigsByManagerIDs_Call { - return &ORM_ListChainConfigsByManagerIDs_Call{Call: _e.mock.On("ListChainConfigsByManagerIDs", mgrIDs)} +func (_e *ORM_Expecter) ListChainConfigsByManagerIDs(ctx interface{}, mgrIDs interface{}) *ORM_ListChainConfigsByManagerIDs_Call { + return &ORM_ListChainConfigsByManagerIDs_Call{Call: _e.mock.On("ListChainConfigsByManagerIDs", ctx, mgrIDs)} } -func (_c *ORM_ListChainConfigsByManagerIDs_Call) Run(run func(mgrIDs []int64)) *ORM_ListChainConfigsByManagerIDs_Call { +func (_c *ORM_ListChainConfigsByManagerIDs_Call) Run(run func(ctx context.Context, mgrIDs []int64)) *ORM_ListChainConfigsByManagerIDs_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].([]int64)) + run(args[0].(context.Context), args[1].([]int64)) }) return _c } @@ -1420,14 +1264,14 @@ func (_c *ORM_ListChainConfigsByManagerIDs_Call) Return(_a0 []feeds.ChainConfig, return _c } -func (_c *ORM_ListChainConfigsByManagerIDs_Call) RunAndReturn(run func([]int64) ([]feeds.ChainConfig, error)) *ORM_ListChainConfigsByManagerIDs_Call { +func (_c *ORM_ListChainConfigsByManagerIDs_Call) RunAndReturn(run func(context.Context, []int64) ([]feeds.ChainConfig, error)) *ORM_ListChainConfigsByManagerIDs_Call { _c.Call.Return(run) return _c } -// ListJobProposals provides a mock function with given fields: -func (_m *ORM) ListJobProposals() ([]feeds.JobProposal, error) { - ret := _m.Called() +// ListJobProposals provides a mock function with given fields: ctx +func (_m *ORM) ListJobProposals(ctx context.Context) ([]feeds.JobProposal, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for ListJobProposals") @@ -1435,19 +1279,19 @@ func (_m *ORM) ListJobProposals() ([]feeds.JobProposal, error) { var r0 []feeds.JobProposal var r1 error - if rf, ok := ret.Get(0).(func() ([]feeds.JobProposal, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) ([]feeds.JobProposal, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() []feeds.JobProposal); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) []feeds.JobProposal); ok { + r0 = rf(ctx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.JobProposal) } } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -1461,13 +1305,14 @@ type ORM_ListJobProposals_Call struct { } // ListJobProposals is a helper method to define mock.On call -func (_e *ORM_Expecter) ListJobProposals() *ORM_ListJobProposals_Call { - return &ORM_ListJobProposals_Call{Call: _e.mock.On("ListJobProposals")} +// - ctx context.Context +func (_e *ORM_Expecter) ListJobProposals(ctx interface{}) *ORM_ListJobProposals_Call { + return &ORM_ListJobProposals_Call{Call: _e.mock.On("ListJobProposals", ctx)} } -func (_c *ORM_ListJobProposals_Call) Run(run func()) *ORM_ListJobProposals_Call { +func (_c *ORM_ListJobProposals_Call) Run(run func(ctx context.Context)) *ORM_ListJobProposals_Call { _c.Call.Run(func(args mock.Arguments) { - run() + run(args[0].(context.Context)) }) return _c } @@ -1477,21 +1322,14 @@ func (_c *ORM_ListJobProposals_Call) Return(jps []feeds.JobProposal, err error) return _c } -func (_c *ORM_ListJobProposals_Call) RunAndReturn(run func() ([]feeds.JobProposal, error)) *ORM_ListJobProposals_Call { +func (_c *ORM_ListJobProposals_Call) RunAndReturn(run func(context.Context) ([]feeds.JobProposal, error)) *ORM_ListJobProposals_Call { _c.Call.Return(run) return _c } -// ListJobProposalsByManagersIDs provides a mock function with given fields: ids, qopts -func (_m *ORM) ListJobProposalsByManagersIDs(ids []int64, qopts ...pg.QOpt) ([]feeds.JobProposal, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, ids) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// ListJobProposalsByManagersIDs provides a mock function with given fields: ctx, ids +func (_m *ORM) ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]feeds.JobProposal, error) { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for ListJobProposalsByManagersIDs") @@ -1499,19 +1337,19 @@ func (_m *ORM) ListJobProposalsByManagersIDs(ids []int64, qopts ...pg.QOpt) ([]f var r0 []feeds.JobProposal var r1 error - if rf, ok := ret.Get(0).(func([]int64, ...pg.QOpt) ([]feeds.JobProposal, error)); ok { - return rf(ids, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]feeds.JobProposal, error)); ok { + return rf(ctx, ids) } - if rf, ok := ret.Get(0).(func([]int64, ...pg.QOpt) []feeds.JobProposal); ok { - r0 = rf(ids, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, []int64) []feeds.JobProposal); ok { + r0 = rf(ctx, ids) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.JobProposal) } } - if rf, ok := ret.Get(1).(func([]int64, ...pg.QOpt) error); ok { - r1 = rf(ids, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok { + r1 = rf(ctx, ids) } else { r1 = ret.Error(1) } @@ -1525,22 +1363,15 @@ type ORM_ListJobProposalsByManagersIDs_Call struct { } // ListJobProposalsByManagersIDs is a helper method to define mock.On call +// - ctx context.Context // - ids []int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) ListJobProposalsByManagersIDs(ids interface{}, qopts ...interface{}) *ORM_ListJobProposalsByManagersIDs_Call { - return &ORM_ListJobProposalsByManagersIDs_Call{Call: _e.mock.On("ListJobProposalsByManagersIDs", - append([]interface{}{ids}, qopts...)...)} +func (_e *ORM_Expecter) ListJobProposalsByManagersIDs(ctx interface{}, ids interface{}) *ORM_ListJobProposalsByManagersIDs_Call { + return &ORM_ListJobProposalsByManagersIDs_Call{Call: _e.mock.On("ListJobProposalsByManagersIDs", ctx, ids)} } -func (_c *ORM_ListJobProposalsByManagersIDs_Call) Run(run func(ids []int64, qopts ...pg.QOpt)) *ORM_ListJobProposalsByManagersIDs_Call { +func (_c *ORM_ListJobProposalsByManagersIDs_Call) Run(run func(ctx context.Context, ids []int64)) *ORM_ListJobProposalsByManagersIDs_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].([]int64), variadicArgs...) + run(args[0].(context.Context), args[1].([]int64)) }) return _c } @@ -1550,14 +1381,14 @@ func (_c *ORM_ListJobProposalsByManagersIDs_Call) Return(_a0 []feeds.JobProposal return _c } -func (_c *ORM_ListJobProposalsByManagersIDs_Call) RunAndReturn(run func([]int64, ...pg.QOpt) ([]feeds.JobProposal, error)) *ORM_ListJobProposalsByManagersIDs_Call { +func (_c *ORM_ListJobProposalsByManagersIDs_Call) RunAndReturn(run func(context.Context, []int64) ([]feeds.JobProposal, error)) *ORM_ListJobProposalsByManagersIDs_Call { _c.Call.Return(run) return _c } -// ListManagers provides a mock function with given fields: -func (_m *ORM) ListManagers() ([]feeds.FeedsManager, error) { - ret := _m.Called() +// ListManagers provides a mock function with given fields: ctx +func (_m *ORM) ListManagers(ctx context.Context) ([]feeds.FeedsManager, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for ListManagers") @@ -1565,19 +1396,19 @@ func (_m *ORM) ListManagers() ([]feeds.FeedsManager, error) { var r0 []feeds.FeedsManager var r1 error - if rf, ok := ret.Get(0).(func() ([]feeds.FeedsManager, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) ([]feeds.FeedsManager, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() []feeds.FeedsManager); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) []feeds.FeedsManager); ok { + r0 = rf(ctx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.FeedsManager) } } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -1591,13 +1422,14 @@ type ORM_ListManagers_Call struct { } // ListManagers is a helper method to define mock.On call -func (_e *ORM_Expecter) ListManagers() *ORM_ListManagers_Call { - return &ORM_ListManagers_Call{Call: _e.mock.On("ListManagers")} +// - ctx context.Context +func (_e *ORM_Expecter) ListManagers(ctx interface{}) *ORM_ListManagers_Call { + return &ORM_ListManagers_Call{Call: _e.mock.On("ListManagers", ctx)} } -func (_c *ORM_ListManagers_Call) Run(run func()) *ORM_ListManagers_Call { +func (_c *ORM_ListManagers_Call) Run(run func(ctx context.Context)) *ORM_ListManagers_Call { _c.Call.Run(func(args mock.Arguments) { - run() + run(args[0].(context.Context)) }) return _c } @@ -1607,14 +1439,14 @@ func (_c *ORM_ListManagers_Call) Return(mgrs []feeds.FeedsManager, err error) *O return _c } -func (_c *ORM_ListManagers_Call) RunAndReturn(run func() ([]feeds.FeedsManager, error)) *ORM_ListManagers_Call { +func (_c *ORM_ListManagers_Call) RunAndReturn(run func(context.Context) ([]feeds.FeedsManager, error)) *ORM_ListManagers_Call { _c.Call.Return(run) return _c } -// ListManagersByIDs provides a mock function with given fields: ids -func (_m *ORM) ListManagersByIDs(ids []int64) ([]feeds.FeedsManager, error) { - ret := _m.Called(ids) +// ListManagersByIDs provides a mock function with given fields: ctx, ids +func (_m *ORM) ListManagersByIDs(ctx context.Context, ids []int64) ([]feeds.FeedsManager, error) { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for ListManagersByIDs") @@ -1622,19 +1454,19 @@ func (_m *ORM) ListManagersByIDs(ids []int64) ([]feeds.FeedsManager, error) { var r0 []feeds.FeedsManager var r1 error - if rf, ok := ret.Get(0).(func([]int64) ([]feeds.FeedsManager, error)); ok { - return rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]feeds.FeedsManager, error)); ok { + return rf(ctx, ids) } - if rf, ok := ret.Get(0).(func([]int64) []feeds.FeedsManager); ok { - r0 = rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) []feeds.FeedsManager); ok { + r0 = rf(ctx, ids) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.FeedsManager) } } - if rf, ok := ret.Get(1).(func([]int64) error); ok { - r1 = rf(ids) + if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok { + r1 = rf(ctx, ids) } else { r1 = ret.Error(1) } @@ -1648,14 +1480,15 @@ type ORM_ListManagersByIDs_Call struct { } // ListManagersByIDs is a helper method to define mock.On call +// - ctx context.Context // - ids []int64 -func (_e *ORM_Expecter) ListManagersByIDs(ids interface{}) *ORM_ListManagersByIDs_Call { - return &ORM_ListManagersByIDs_Call{Call: _e.mock.On("ListManagersByIDs", ids)} +func (_e *ORM_Expecter) ListManagersByIDs(ctx interface{}, ids interface{}) *ORM_ListManagersByIDs_Call { + return &ORM_ListManagersByIDs_Call{Call: _e.mock.On("ListManagersByIDs", ctx, ids)} } -func (_c *ORM_ListManagersByIDs_Call) Run(run func(ids []int64)) *ORM_ListManagersByIDs_Call { +func (_c *ORM_ListManagersByIDs_Call) Run(run func(ctx context.Context, ids []int64)) *ORM_ListManagersByIDs_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].([]int64)) + run(args[0].(context.Context), args[1].([]int64)) }) return _c } @@ -1665,21 +1498,14 @@ func (_c *ORM_ListManagersByIDs_Call) Return(_a0 []feeds.FeedsManager, _a1 error return _c } -func (_c *ORM_ListManagersByIDs_Call) RunAndReturn(run func([]int64) ([]feeds.FeedsManager, error)) *ORM_ListManagersByIDs_Call { +func (_c *ORM_ListManagersByIDs_Call) RunAndReturn(run func(context.Context, []int64) ([]feeds.FeedsManager, error)) *ORM_ListManagersByIDs_Call { _c.Call.Return(run) return _c } -// ListSpecsByJobProposalIDs provides a mock function with given fields: ids, qopts -func (_m *ORM) ListSpecsByJobProposalIDs(ids []int64, qopts ...pg.QOpt) ([]feeds.JobProposalSpec, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, ids) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// ListSpecsByJobProposalIDs provides a mock function with given fields: ctx, ids +func (_m *ORM) ListSpecsByJobProposalIDs(ctx context.Context, ids []int64) ([]feeds.JobProposalSpec, error) { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for ListSpecsByJobProposalIDs") @@ -1687,19 +1513,19 @@ func (_m *ORM) ListSpecsByJobProposalIDs(ids []int64, qopts ...pg.QOpt) ([]feeds var r0 []feeds.JobProposalSpec var r1 error - if rf, ok := ret.Get(0).(func([]int64, ...pg.QOpt) ([]feeds.JobProposalSpec, error)); ok { - return rf(ids, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]feeds.JobProposalSpec, error)); ok { + return rf(ctx, ids) } - if rf, ok := ret.Get(0).(func([]int64, ...pg.QOpt) []feeds.JobProposalSpec); ok { - r0 = rf(ids, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, []int64) []feeds.JobProposalSpec); ok { + r0 = rf(ctx, ids) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.JobProposalSpec) } } - if rf, ok := ret.Get(1).(func([]int64, ...pg.QOpt) error); ok { - r1 = rf(ids, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok { + r1 = rf(ctx, ids) } else { r1 = ret.Error(1) } @@ -1713,22 +1539,15 @@ type ORM_ListSpecsByJobProposalIDs_Call struct { } // ListSpecsByJobProposalIDs is a helper method to define mock.On call +// - ctx context.Context // - ids []int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) ListSpecsByJobProposalIDs(ids interface{}, qopts ...interface{}) *ORM_ListSpecsByJobProposalIDs_Call { - return &ORM_ListSpecsByJobProposalIDs_Call{Call: _e.mock.On("ListSpecsByJobProposalIDs", - append([]interface{}{ids}, qopts...)...)} +func (_e *ORM_Expecter) ListSpecsByJobProposalIDs(ctx interface{}, ids interface{}) *ORM_ListSpecsByJobProposalIDs_Call { + return &ORM_ListSpecsByJobProposalIDs_Call{Call: _e.mock.On("ListSpecsByJobProposalIDs", ctx, ids)} } -func (_c *ORM_ListSpecsByJobProposalIDs_Call) Run(run func(ids []int64, qopts ...pg.QOpt)) *ORM_ListSpecsByJobProposalIDs_Call { +func (_c *ORM_ListSpecsByJobProposalIDs_Call) Run(run func(ctx context.Context, ids []int64)) *ORM_ListSpecsByJobProposalIDs_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].([]int64), variadicArgs...) + run(args[0].(context.Context), args[1].([]int64)) }) return _c } @@ -1738,29 +1557,22 @@ func (_c *ORM_ListSpecsByJobProposalIDs_Call) Return(_a0 []feeds.JobProposalSpec return _c } -func (_c *ORM_ListSpecsByJobProposalIDs_Call) RunAndReturn(run func([]int64, ...pg.QOpt) ([]feeds.JobProposalSpec, error)) *ORM_ListSpecsByJobProposalIDs_Call { +func (_c *ORM_ListSpecsByJobProposalIDs_Call) RunAndReturn(run func(context.Context, []int64) ([]feeds.JobProposalSpec, error)) *ORM_ListSpecsByJobProposalIDs_Call { _c.Call.Return(run) return _c } -// RejectSpec provides a mock function with given fields: id, qopts -func (_m *ORM) RejectSpec(id int64, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// RejectSpec provides a mock function with given fields: ctx, id +func (_m *ORM) RejectSpec(ctx context.Context, id int64) error { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for RejectSpec") } var r0 error - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) error); ok { - r0 = rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok { + r0 = rf(ctx, id) } else { r0 = ret.Error(0) } @@ -1774,22 +1586,15 @@ type ORM_RejectSpec_Call struct { } // RejectSpec is a helper method to define mock.On call +// - ctx context.Context // - id int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) RejectSpec(id interface{}, qopts ...interface{}) *ORM_RejectSpec_Call { - return &ORM_RejectSpec_Call{Call: _e.mock.On("RejectSpec", - append([]interface{}{id}, qopts...)...)} +func (_e *ORM_Expecter) RejectSpec(ctx interface{}, id interface{}) *ORM_RejectSpec_Call { + return &ORM_RejectSpec_Call{Call: _e.mock.On("RejectSpec", ctx, id)} } -func (_c *ORM_RejectSpec_Call) Run(run func(id int64, qopts ...pg.QOpt)) *ORM_RejectSpec_Call { +func (_c *ORM_RejectSpec_Call) Run(run func(ctx context.Context, id int64)) *ORM_RejectSpec_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), variadicArgs...) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -1799,29 +1604,22 @@ func (_c *ORM_RejectSpec_Call) Return(_a0 error) *ORM_RejectSpec_Call { return _c } -func (_c *ORM_RejectSpec_Call) RunAndReturn(run func(int64, ...pg.QOpt) error) *ORM_RejectSpec_Call { +func (_c *ORM_RejectSpec_Call) RunAndReturn(run func(context.Context, int64) error) *ORM_RejectSpec_Call { _c.Call.Return(run) return _c } -// RevokeSpec provides a mock function with given fields: id, qopts -func (_m *ORM) RevokeSpec(id int64, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// RevokeSpec provides a mock function with given fields: ctx, id +func (_m *ORM) RevokeSpec(ctx context.Context, id int64) error { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for RevokeSpec") } var r0 error - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) error); ok { - r0 = rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok { + r0 = rf(ctx, id) } else { r0 = ret.Error(0) } @@ -1835,22 +1633,15 @@ type ORM_RevokeSpec_Call struct { } // RevokeSpec is a helper method to define mock.On call +// - ctx context.Context // - id int64 -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) RevokeSpec(id interface{}, qopts ...interface{}) *ORM_RevokeSpec_Call { - return &ORM_RevokeSpec_Call{Call: _e.mock.On("RevokeSpec", - append([]interface{}{id}, qopts...)...)} +func (_e *ORM_Expecter) RevokeSpec(ctx interface{}, id interface{}) *ORM_RevokeSpec_Call { + return &ORM_RevokeSpec_Call{Call: _e.mock.On("RevokeSpec", ctx, id)} } -func (_c *ORM_RevokeSpec_Call) Run(run func(id int64, qopts ...pg.QOpt)) *ORM_RevokeSpec_Call { +func (_c *ORM_RevokeSpec_Call) Run(run func(ctx context.Context, id int64)) *ORM_RevokeSpec_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), variadicArgs...) + run(args[0].(context.Context), args[1].(int64)) }) return _c } @@ -1860,14 +1651,61 @@ func (_c *ORM_RevokeSpec_Call) Return(_a0 error) *ORM_RevokeSpec_Call { return _c } -func (_c *ORM_RevokeSpec_Call) RunAndReturn(run func(int64, ...pg.QOpt) error) *ORM_RevokeSpec_Call { +func (_c *ORM_RevokeSpec_Call) RunAndReturn(run func(context.Context, int64) error) *ORM_RevokeSpec_Call { _c.Call.Return(run) return _c } -// UpdateChainConfig provides a mock function with given fields: cfg -func (_m *ORM) UpdateChainConfig(cfg feeds.ChainConfig) (int64, error) { - ret := _m.Called(cfg) +// Transact provides a mock function with given fields: _a0, _a1 +func (_m *ORM) Transact(_a0 context.Context, _a1 func(feeds.ORM) error) error { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for Transact") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, func(feeds.ORM) error) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ORM_Transact_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Transact' +type ORM_Transact_Call struct { + *mock.Call +} + +// Transact is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 func(feeds.ORM) error +func (_e *ORM_Expecter) Transact(_a0 interface{}, _a1 interface{}) *ORM_Transact_Call { + return &ORM_Transact_Call{Call: _e.mock.On("Transact", _a0, _a1)} +} + +func (_c *ORM_Transact_Call) Run(run func(_a0 context.Context, _a1 func(feeds.ORM) error)) *ORM_Transact_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(func(feeds.ORM) error)) + }) + return _c +} + +func (_c *ORM_Transact_Call) Return(_a0 error) *ORM_Transact_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ORM_Transact_Call) RunAndReturn(run func(context.Context, func(feeds.ORM) error) error) *ORM_Transact_Call { + _c.Call.Return(run) + return _c +} + +// UpdateChainConfig provides a mock function with given fields: ctx, cfg +func (_m *ORM) UpdateChainConfig(ctx context.Context, cfg feeds.ChainConfig) (int64, error) { + ret := _m.Called(ctx, cfg) if len(ret) == 0 { panic("no return value specified for UpdateChainConfig") @@ -1875,17 +1713,17 @@ func (_m *ORM) UpdateChainConfig(cfg feeds.ChainConfig) (int64, error) { var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func(feeds.ChainConfig) (int64, error)); ok { - return rf(cfg) + if rf, ok := ret.Get(0).(func(context.Context, feeds.ChainConfig) (int64, error)); ok { + return rf(ctx, cfg) } - if rf, ok := ret.Get(0).(func(feeds.ChainConfig) int64); ok { - r0 = rf(cfg) + if rf, ok := ret.Get(0).(func(context.Context, feeds.ChainConfig) int64); ok { + r0 = rf(ctx, cfg) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func(feeds.ChainConfig) error); ok { - r1 = rf(cfg) + if rf, ok := ret.Get(1).(func(context.Context, feeds.ChainConfig) error); ok { + r1 = rf(ctx, cfg) } else { r1 = ret.Error(1) } @@ -1899,14 +1737,15 @@ type ORM_UpdateChainConfig_Call struct { } // UpdateChainConfig is a helper method to define mock.On call +// - ctx context.Context // - cfg feeds.ChainConfig -func (_e *ORM_Expecter) UpdateChainConfig(cfg interface{}) *ORM_UpdateChainConfig_Call { - return &ORM_UpdateChainConfig_Call{Call: _e.mock.On("UpdateChainConfig", cfg)} +func (_e *ORM_Expecter) UpdateChainConfig(ctx interface{}, cfg interface{}) *ORM_UpdateChainConfig_Call { + return &ORM_UpdateChainConfig_Call{Call: _e.mock.On("UpdateChainConfig", ctx, cfg)} } -func (_c *ORM_UpdateChainConfig_Call) Run(run func(cfg feeds.ChainConfig)) *ORM_UpdateChainConfig_Call { +func (_c *ORM_UpdateChainConfig_Call) Run(run func(ctx context.Context, cfg feeds.ChainConfig)) *ORM_UpdateChainConfig_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(feeds.ChainConfig)) + run(args[0].(context.Context), args[1].(feeds.ChainConfig)) }) return _c } @@ -1916,29 +1755,22 @@ func (_c *ORM_UpdateChainConfig_Call) Return(_a0 int64, _a1 error) *ORM_UpdateCh return _c } -func (_c *ORM_UpdateChainConfig_Call) RunAndReturn(run func(feeds.ChainConfig) (int64, error)) *ORM_UpdateChainConfig_Call { +func (_c *ORM_UpdateChainConfig_Call) RunAndReturn(run func(context.Context, feeds.ChainConfig) (int64, error)) *ORM_UpdateChainConfig_Call { _c.Call.Return(run) return _c } -// UpdateJobProposalStatus provides a mock function with given fields: id, status, qopts -func (_m *ORM) UpdateJobProposalStatus(id int64, status feeds.JobProposalStatus, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id, status) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// UpdateJobProposalStatus provides a mock function with given fields: ctx, id, status +func (_m *ORM) UpdateJobProposalStatus(ctx context.Context, id int64, status feeds.JobProposalStatus) error { + ret := _m.Called(ctx, id, status) if len(ret) == 0 { panic("no return value specified for UpdateJobProposalStatus") } var r0 error - if rf, ok := ret.Get(0).(func(int64, feeds.JobProposalStatus, ...pg.QOpt) error); ok { - r0 = rf(id, status, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64, feeds.JobProposalStatus) error); ok { + r0 = rf(ctx, id, status) } else { r0 = ret.Error(0) } @@ -1952,23 +1784,16 @@ type ORM_UpdateJobProposalStatus_Call struct { } // UpdateJobProposalStatus is a helper method to define mock.On call +// - ctx context.Context // - id int64 // - status feeds.JobProposalStatus -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) UpdateJobProposalStatus(id interface{}, status interface{}, qopts ...interface{}) *ORM_UpdateJobProposalStatus_Call { - return &ORM_UpdateJobProposalStatus_Call{Call: _e.mock.On("UpdateJobProposalStatus", - append([]interface{}{id, status}, qopts...)...)} +func (_e *ORM_Expecter) UpdateJobProposalStatus(ctx interface{}, id interface{}, status interface{}) *ORM_UpdateJobProposalStatus_Call { + return &ORM_UpdateJobProposalStatus_Call{Call: _e.mock.On("UpdateJobProposalStatus", ctx, id, status)} } -func (_c *ORM_UpdateJobProposalStatus_Call) Run(run func(id int64, status feeds.JobProposalStatus, qopts ...pg.QOpt)) *ORM_UpdateJobProposalStatus_Call { +func (_c *ORM_UpdateJobProposalStatus_Call) Run(run func(ctx context.Context, id int64, status feeds.JobProposalStatus)) *ORM_UpdateJobProposalStatus_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), args[1].(feeds.JobProposalStatus), variadicArgs...) + run(args[0].(context.Context), args[1].(int64), args[2].(feeds.JobProposalStatus)) }) return _c } @@ -1978,29 +1803,22 @@ func (_c *ORM_UpdateJobProposalStatus_Call) Return(_a0 error) *ORM_UpdateJobProp return _c } -func (_c *ORM_UpdateJobProposalStatus_Call) RunAndReturn(run func(int64, feeds.JobProposalStatus, ...pg.QOpt) error) *ORM_UpdateJobProposalStatus_Call { +func (_c *ORM_UpdateJobProposalStatus_Call) RunAndReturn(run func(context.Context, int64, feeds.JobProposalStatus) error) *ORM_UpdateJobProposalStatus_Call { _c.Call.Return(run) return _c } -// UpdateManager provides a mock function with given fields: mgr, qopts -func (_m *ORM) UpdateManager(mgr feeds.FeedsManager, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, mgr) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// UpdateManager provides a mock function with given fields: ctx, mgr +func (_m *ORM) UpdateManager(ctx context.Context, mgr feeds.FeedsManager) error { + ret := _m.Called(ctx, mgr) if len(ret) == 0 { panic("no return value specified for UpdateManager") } var r0 error - if rf, ok := ret.Get(0).(func(feeds.FeedsManager, ...pg.QOpt) error); ok { - r0 = rf(mgr, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, feeds.FeedsManager) error); ok { + r0 = rf(ctx, mgr) } else { r0 = ret.Error(0) } @@ -2014,22 +1832,15 @@ type ORM_UpdateManager_Call struct { } // UpdateManager is a helper method to define mock.On call +// - ctx context.Context // - mgr feeds.FeedsManager -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) UpdateManager(mgr interface{}, qopts ...interface{}) *ORM_UpdateManager_Call { - return &ORM_UpdateManager_Call{Call: _e.mock.On("UpdateManager", - append([]interface{}{mgr}, qopts...)...)} +func (_e *ORM_Expecter) UpdateManager(ctx interface{}, mgr interface{}) *ORM_UpdateManager_Call { + return &ORM_UpdateManager_Call{Call: _e.mock.On("UpdateManager", ctx, mgr)} } -func (_c *ORM_UpdateManager_Call) Run(run func(mgr feeds.FeedsManager, qopts ...pg.QOpt)) *ORM_UpdateManager_Call { +func (_c *ORM_UpdateManager_Call) Run(run func(ctx context.Context, mgr feeds.FeedsManager)) *ORM_UpdateManager_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(feeds.FeedsManager), variadicArgs...) + run(args[0].(context.Context), args[1].(feeds.FeedsManager)) }) return _c } @@ -2039,29 +1850,22 @@ func (_c *ORM_UpdateManager_Call) Return(_a0 error) *ORM_UpdateManager_Call { return _c } -func (_c *ORM_UpdateManager_Call) RunAndReturn(run func(feeds.FeedsManager, ...pg.QOpt) error) *ORM_UpdateManager_Call { +func (_c *ORM_UpdateManager_Call) RunAndReturn(run func(context.Context, feeds.FeedsManager) error) *ORM_UpdateManager_Call { _c.Call.Return(run) return _c } -// UpdateSpecDefinition provides a mock function with given fields: id, spec, qopts -func (_m *ORM) UpdateSpecDefinition(id int64, spec string, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id, spec) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// UpdateSpecDefinition provides a mock function with given fields: ctx, id, spec +func (_m *ORM) UpdateSpecDefinition(ctx context.Context, id int64, spec string) error { + ret := _m.Called(ctx, id, spec) if len(ret) == 0 { panic("no return value specified for UpdateSpecDefinition") } var r0 error - if rf, ok := ret.Get(0).(func(int64, string, ...pg.QOpt) error); ok { - r0 = rf(id, spec, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64, string) error); ok { + r0 = rf(ctx, id, spec) } else { r0 = ret.Error(0) } @@ -2075,23 +1879,16 @@ type ORM_UpdateSpecDefinition_Call struct { } // UpdateSpecDefinition is a helper method to define mock.On call +// - ctx context.Context // - id int64 // - spec string -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) UpdateSpecDefinition(id interface{}, spec interface{}, qopts ...interface{}) *ORM_UpdateSpecDefinition_Call { - return &ORM_UpdateSpecDefinition_Call{Call: _e.mock.On("UpdateSpecDefinition", - append([]interface{}{id, spec}, qopts...)...)} +func (_e *ORM_Expecter) UpdateSpecDefinition(ctx interface{}, id interface{}, spec interface{}) *ORM_UpdateSpecDefinition_Call { + return &ORM_UpdateSpecDefinition_Call{Call: _e.mock.On("UpdateSpecDefinition", ctx, id, spec)} } -func (_c *ORM_UpdateSpecDefinition_Call) Run(run func(id int64, spec string, qopts ...pg.QOpt)) *ORM_UpdateSpecDefinition_Call { +func (_c *ORM_UpdateSpecDefinition_Call) Run(run func(ctx context.Context, id int64, spec string)) *ORM_UpdateSpecDefinition_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(int64), args[1].(string), variadicArgs...) + run(args[0].(context.Context), args[1].(int64), args[2].(string)) }) return _c } @@ -2101,21 +1898,14 @@ func (_c *ORM_UpdateSpecDefinition_Call) Return(_a0 error) *ORM_UpdateSpecDefini return _c } -func (_c *ORM_UpdateSpecDefinition_Call) RunAndReturn(run func(int64, string, ...pg.QOpt) error) *ORM_UpdateSpecDefinition_Call { +func (_c *ORM_UpdateSpecDefinition_Call) RunAndReturn(run func(context.Context, int64, string) error) *ORM_UpdateSpecDefinition_Call { _c.Call.Return(run) return _c } -// UpsertJobProposal provides a mock function with given fields: jp, qopts -func (_m *ORM) UpsertJobProposal(jp *feeds.JobProposal, qopts ...pg.QOpt) (int64, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, jp) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// UpsertJobProposal provides a mock function with given fields: ctx, jp +func (_m *ORM) UpsertJobProposal(ctx context.Context, jp *feeds.JobProposal) (int64, error) { + ret := _m.Called(ctx, jp) if len(ret) == 0 { panic("no return value specified for UpsertJobProposal") @@ -2123,17 +1913,17 @@ func (_m *ORM) UpsertJobProposal(jp *feeds.JobProposal, qopts ...pg.QOpt) (int64 var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func(*feeds.JobProposal, ...pg.QOpt) (int64, error)); ok { - return rf(jp, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, *feeds.JobProposal) (int64, error)); ok { + return rf(ctx, jp) } - if rf, ok := ret.Get(0).(func(*feeds.JobProposal, ...pg.QOpt) int64); ok { - r0 = rf(jp, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, *feeds.JobProposal) int64); ok { + r0 = rf(ctx, jp) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func(*feeds.JobProposal, ...pg.QOpt) error); ok { - r1 = rf(jp, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, *feeds.JobProposal) error); ok { + r1 = rf(ctx, jp) } else { r1 = ret.Error(1) } @@ -2147,22 +1937,15 @@ type ORM_UpsertJobProposal_Call struct { } // UpsertJobProposal is a helper method to define mock.On call +// - ctx context.Context // - jp *feeds.JobProposal -// - qopts ...pg.QOpt -func (_e *ORM_Expecter) UpsertJobProposal(jp interface{}, qopts ...interface{}) *ORM_UpsertJobProposal_Call { - return &ORM_UpsertJobProposal_Call{Call: _e.mock.On("UpsertJobProposal", - append([]interface{}{jp}, qopts...)...)} +func (_e *ORM_Expecter) UpsertJobProposal(ctx interface{}, jp interface{}) *ORM_UpsertJobProposal_Call { + return &ORM_UpsertJobProposal_Call{Call: _e.mock.On("UpsertJobProposal", ctx, jp)} } -func (_c *ORM_UpsertJobProposal_Call) Run(run func(jp *feeds.JobProposal, qopts ...pg.QOpt)) *ORM_UpsertJobProposal_Call { +func (_c *ORM_UpsertJobProposal_Call) Run(run func(ctx context.Context, jp *feeds.JobProposal)) *ORM_UpsertJobProposal_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]pg.QOpt, len(args)-1) - for i, a := range args[1:] { - if a != nil { - variadicArgs[i] = a.(pg.QOpt) - } - } - run(args[0].(*feeds.JobProposal), variadicArgs...) + run(args[0].(context.Context), args[1].(*feeds.JobProposal)) }) return _c } @@ -2172,7 +1955,55 @@ func (_c *ORM_UpsertJobProposal_Call) Return(_a0 int64, _a1 error) *ORM_UpsertJo return _c } -func (_c *ORM_UpsertJobProposal_Call) RunAndReturn(run func(*feeds.JobProposal, ...pg.QOpt) (int64, error)) *ORM_UpsertJobProposal_Call { +func (_c *ORM_UpsertJobProposal_Call) RunAndReturn(run func(context.Context, *feeds.JobProposal) (int64, error)) *ORM_UpsertJobProposal_Call { + _c.Call.Return(run) + return _c +} + +// WithDataSource provides a mock function with given fields: _a0 +func (_m *ORM) WithDataSource(_a0 sqlutil.DataSource) feeds.ORM { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for WithDataSource") + } + + var r0 feeds.ORM + if rf, ok := ret.Get(0).(func(sqlutil.DataSource) feeds.ORM); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(feeds.ORM) + } + } + + return r0 +} + +// ORM_WithDataSource_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WithDataSource' +type ORM_WithDataSource_Call struct { + *mock.Call +} + +// WithDataSource is a helper method to define mock.On call +// - _a0 sqlutil.DataSource +func (_e *ORM_Expecter) WithDataSource(_a0 interface{}) *ORM_WithDataSource_Call { + return &ORM_WithDataSource_Call{Call: _e.mock.On("WithDataSource", _a0)} +} + +func (_c *ORM_WithDataSource_Call) Run(run func(_a0 sqlutil.DataSource)) *ORM_WithDataSource_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(sqlutil.DataSource)) + }) + return _c +} + +func (_c *ORM_WithDataSource_Call) Return(_a0 feeds.ORM) *ORM_WithDataSource_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ORM_WithDataSource_Call) RunAndReturn(run func(sqlutil.DataSource) feeds.ORM) *ORM_WithDataSource_Call { _c.Call.Return(run) return _c } diff --git a/core/services/feeds/mocks/service.go b/core/services/feeds/mocks/service.go index 05ede181f44..1e2e6393276 100644 --- a/core/services/feeds/mocks/service.go +++ b/core/services/feeds/mocks/service.go @@ -68,9 +68,9 @@ func (_m *Service) Close() error { return r0 } -// CountJobProposalsByStatus provides a mock function with given fields: -func (_m *Service) CountJobProposalsByStatus() (*feeds.JobProposalCounts, error) { - ret := _m.Called() +// CountJobProposalsByStatus provides a mock function with given fields: ctx +func (_m *Service) CountJobProposalsByStatus(ctx context.Context) (*feeds.JobProposalCounts, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for CountJobProposalsByStatus") @@ -78,19 +78,19 @@ func (_m *Service) CountJobProposalsByStatus() (*feeds.JobProposalCounts, error) var r0 *feeds.JobProposalCounts var r1 error - if rf, ok := ret.Get(0).(func() (*feeds.JobProposalCounts, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (*feeds.JobProposalCounts, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() *feeds.JobProposalCounts); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) *feeds.JobProposalCounts); ok { + r0 = rf(ctx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.JobProposalCounts) } } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -98,9 +98,9 @@ func (_m *Service) CountJobProposalsByStatus() (*feeds.JobProposalCounts, error) return r0, r1 } -// CountManagers provides a mock function with given fields: -func (_m *Service) CountManagers() (int64, error) { - ret := _m.Called() +// CountManagers provides a mock function with given fields: ctx +func (_m *Service) CountManagers(ctx context.Context) (int64, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for CountManagers") @@ -108,17 +108,17 @@ func (_m *Service) CountManagers() (int64, error) { var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func() (int64, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (int64, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() int64); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) int64); ok { + r0 = rf(ctx) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -210,9 +210,9 @@ func (_m *Service) DeleteJob(ctx context.Context, args *feeds.DeleteJobArgs) (in return r0, r1 } -// GetChainConfig provides a mock function with given fields: id -func (_m *Service) GetChainConfig(id int64) (*feeds.ChainConfig, error) { - ret := _m.Called(id) +// GetChainConfig provides a mock function with given fields: ctx, id +func (_m *Service) GetChainConfig(ctx context.Context, id int64) (*feeds.ChainConfig, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for GetChainConfig") @@ -220,19 +220,19 @@ func (_m *Service) GetChainConfig(id int64) (*feeds.ChainConfig, error) { var r0 *feeds.ChainConfig var r1 error - if rf, ok := ret.Get(0).(func(int64) (*feeds.ChainConfig, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.ChainConfig, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64) *feeds.ChainConfig); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.ChainConfig); ok { + r0 = rf(ctx, id) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.ChainConfig) } } - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -240,9 +240,9 @@ func (_m *Service) GetChainConfig(id int64) (*feeds.ChainConfig, error) { return r0, r1 } -// GetJobProposal provides a mock function with given fields: id -func (_m *Service) GetJobProposal(id int64) (*feeds.JobProposal, error) { - ret := _m.Called(id) +// GetJobProposal provides a mock function with given fields: ctx, id +func (_m *Service) GetJobProposal(ctx context.Context, id int64) (*feeds.JobProposal, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for GetJobProposal") @@ -250,19 +250,19 @@ func (_m *Service) GetJobProposal(id int64) (*feeds.JobProposal, error) { var r0 *feeds.JobProposal var r1 error - if rf, ok := ret.Get(0).(func(int64) (*feeds.JobProposal, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.JobProposal, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64) *feeds.JobProposal); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.JobProposal); ok { + r0 = rf(ctx, id) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.JobProposal) } } - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -270,9 +270,9 @@ func (_m *Service) GetJobProposal(id int64) (*feeds.JobProposal, error) { return r0, r1 } -// GetManager provides a mock function with given fields: id -func (_m *Service) GetManager(id int64) (*feeds.FeedsManager, error) { - ret := _m.Called(id) +// GetManager provides a mock function with given fields: ctx, id +func (_m *Service) GetManager(ctx context.Context, id int64) (*feeds.FeedsManager, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for GetManager") @@ -280,19 +280,19 @@ func (_m *Service) GetManager(id int64) (*feeds.FeedsManager, error) { var r0 *feeds.FeedsManager var r1 error - if rf, ok := ret.Get(0).(func(int64) (*feeds.FeedsManager, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.FeedsManager, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64) *feeds.FeedsManager); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.FeedsManager); ok { + r0 = rf(ctx, id) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.FeedsManager) } } - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -300,9 +300,9 @@ func (_m *Service) GetManager(id int64) (*feeds.FeedsManager, error) { return r0, r1 } -// GetSpec provides a mock function with given fields: id -func (_m *Service) GetSpec(id int64) (*feeds.JobProposalSpec, error) { - ret := _m.Called(id) +// GetSpec provides a mock function with given fields: ctx, id +func (_m *Service) GetSpec(ctx context.Context, id int64) (*feeds.JobProposalSpec, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for GetSpec") @@ -310,19 +310,19 @@ func (_m *Service) GetSpec(id int64) (*feeds.JobProposalSpec, error) { var r0 *feeds.JobProposalSpec var r1 error - if rf, ok := ret.Get(0).(func(int64) (*feeds.JobProposalSpec, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) (*feeds.JobProposalSpec, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64) *feeds.JobProposalSpec); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) *feeds.JobProposalSpec); ok { + r0 = rf(ctx, id) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*feeds.JobProposalSpec) } } - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -358,9 +358,9 @@ func (_m *Service) IsJobManaged(ctx context.Context, jobID int64) (bool, error) return r0, r1 } -// ListChainConfigsByManagerIDs provides a mock function with given fields: mgrIDs -func (_m *Service) ListChainConfigsByManagerIDs(mgrIDs []int64) ([]feeds.ChainConfig, error) { - ret := _m.Called(mgrIDs) +// ListChainConfigsByManagerIDs provides a mock function with given fields: ctx, mgrIDs +func (_m *Service) ListChainConfigsByManagerIDs(ctx context.Context, mgrIDs []int64) ([]feeds.ChainConfig, error) { + ret := _m.Called(ctx, mgrIDs) if len(ret) == 0 { panic("no return value specified for ListChainConfigsByManagerIDs") @@ -368,19 +368,19 @@ func (_m *Service) ListChainConfigsByManagerIDs(mgrIDs []int64) ([]feeds.ChainCo var r0 []feeds.ChainConfig var r1 error - if rf, ok := ret.Get(0).(func([]int64) ([]feeds.ChainConfig, error)); ok { - return rf(mgrIDs) + if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]feeds.ChainConfig, error)); ok { + return rf(ctx, mgrIDs) } - if rf, ok := ret.Get(0).(func([]int64) []feeds.ChainConfig); ok { - r0 = rf(mgrIDs) + if rf, ok := ret.Get(0).(func(context.Context, []int64) []feeds.ChainConfig); ok { + r0 = rf(ctx, mgrIDs) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.ChainConfig) } } - if rf, ok := ret.Get(1).(func([]int64) error); ok { - r1 = rf(mgrIDs) + if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok { + r1 = rf(ctx, mgrIDs) } else { r1 = ret.Error(1) } @@ -388,9 +388,9 @@ func (_m *Service) ListChainConfigsByManagerIDs(mgrIDs []int64) ([]feeds.ChainCo return r0, r1 } -// ListJobProposals provides a mock function with given fields: -func (_m *Service) ListJobProposals() ([]feeds.JobProposal, error) { - ret := _m.Called() +// ListJobProposals provides a mock function with given fields: ctx +func (_m *Service) ListJobProposals(ctx context.Context) ([]feeds.JobProposal, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for ListJobProposals") @@ -398,19 +398,19 @@ func (_m *Service) ListJobProposals() ([]feeds.JobProposal, error) { var r0 []feeds.JobProposal var r1 error - if rf, ok := ret.Get(0).(func() ([]feeds.JobProposal, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) ([]feeds.JobProposal, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() []feeds.JobProposal); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) []feeds.JobProposal); ok { + r0 = rf(ctx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.JobProposal) } } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -418,9 +418,9 @@ func (_m *Service) ListJobProposals() ([]feeds.JobProposal, error) { return r0, r1 } -// ListJobProposalsByManagersIDs provides a mock function with given fields: ids -func (_m *Service) ListJobProposalsByManagersIDs(ids []int64) ([]feeds.JobProposal, error) { - ret := _m.Called(ids) +// ListJobProposalsByManagersIDs provides a mock function with given fields: ctx, ids +func (_m *Service) ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]feeds.JobProposal, error) { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for ListJobProposalsByManagersIDs") @@ -428,19 +428,19 @@ func (_m *Service) ListJobProposalsByManagersIDs(ids []int64) ([]feeds.JobPropos var r0 []feeds.JobProposal var r1 error - if rf, ok := ret.Get(0).(func([]int64) ([]feeds.JobProposal, error)); ok { - return rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]feeds.JobProposal, error)); ok { + return rf(ctx, ids) } - if rf, ok := ret.Get(0).(func([]int64) []feeds.JobProposal); ok { - r0 = rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) []feeds.JobProposal); ok { + r0 = rf(ctx, ids) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.JobProposal) } } - if rf, ok := ret.Get(1).(func([]int64) error); ok { - r1 = rf(ids) + if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok { + r1 = rf(ctx, ids) } else { r1 = ret.Error(1) } @@ -448,9 +448,9 @@ func (_m *Service) ListJobProposalsByManagersIDs(ids []int64) ([]feeds.JobPropos return r0, r1 } -// ListManagers provides a mock function with given fields: -func (_m *Service) ListManagers() ([]feeds.FeedsManager, error) { - ret := _m.Called() +// ListManagers provides a mock function with given fields: ctx +func (_m *Service) ListManagers(ctx context.Context) ([]feeds.FeedsManager, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for ListManagers") @@ -458,19 +458,19 @@ func (_m *Service) ListManagers() ([]feeds.FeedsManager, error) { var r0 []feeds.FeedsManager var r1 error - if rf, ok := ret.Get(0).(func() ([]feeds.FeedsManager, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) ([]feeds.FeedsManager, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() []feeds.FeedsManager); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) []feeds.FeedsManager); ok { + r0 = rf(ctx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.FeedsManager) } } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -478,9 +478,9 @@ func (_m *Service) ListManagers() ([]feeds.FeedsManager, error) { return r0, r1 } -// ListManagersByIDs provides a mock function with given fields: ids -func (_m *Service) ListManagersByIDs(ids []int64) ([]feeds.FeedsManager, error) { - ret := _m.Called(ids) +// ListManagersByIDs provides a mock function with given fields: ctx, ids +func (_m *Service) ListManagersByIDs(ctx context.Context, ids []int64) ([]feeds.FeedsManager, error) { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for ListManagersByIDs") @@ -488,19 +488,19 @@ func (_m *Service) ListManagersByIDs(ids []int64) ([]feeds.FeedsManager, error) var r0 []feeds.FeedsManager var r1 error - if rf, ok := ret.Get(0).(func([]int64) ([]feeds.FeedsManager, error)); ok { - return rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]feeds.FeedsManager, error)); ok { + return rf(ctx, ids) } - if rf, ok := ret.Get(0).(func([]int64) []feeds.FeedsManager); ok { - r0 = rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) []feeds.FeedsManager); ok { + r0 = rf(ctx, ids) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.FeedsManager) } } - if rf, ok := ret.Get(1).(func([]int64) error); ok { - r1 = rf(ids) + if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok { + r1 = rf(ctx, ids) } else { r1 = ret.Error(1) } @@ -508,9 +508,9 @@ func (_m *Service) ListManagersByIDs(ids []int64) ([]feeds.FeedsManager, error) return r0, r1 } -// ListSpecsByJobProposalIDs provides a mock function with given fields: ids -func (_m *Service) ListSpecsByJobProposalIDs(ids []int64) ([]feeds.JobProposalSpec, error) { - ret := _m.Called(ids) +// ListSpecsByJobProposalIDs provides a mock function with given fields: ctx, ids +func (_m *Service) ListSpecsByJobProposalIDs(ctx context.Context, ids []int64) ([]feeds.JobProposalSpec, error) { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for ListSpecsByJobProposalIDs") @@ -518,19 +518,19 @@ func (_m *Service) ListSpecsByJobProposalIDs(ids []int64) ([]feeds.JobProposalSp var r0 []feeds.JobProposalSpec var r1 error - if rf, ok := ret.Get(0).(func([]int64) ([]feeds.JobProposalSpec, error)); ok { - return rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]feeds.JobProposalSpec, error)); ok { + return rf(ctx, ids) } - if rf, ok := ret.Get(0).(func([]int64) []feeds.JobProposalSpec); ok { - r0 = rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) []feeds.JobProposalSpec); ok { + r0 = rf(ctx, ids) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]feeds.JobProposalSpec) } } - if rf, ok := ret.Get(1).(func([]int64) error); ok { - r1 = rf(ids) + if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok { + r1 = rf(ctx, ids) } else { r1 = ret.Error(1) } @@ -676,11 +676,6 @@ func (_m *Service) SyncNodeInfo(ctx context.Context, id int64) error { return r0 } -// Unsafe_SetConnectionsManager provides a mock function with given fields: _a0 -func (_m *Service) Unsafe_SetConnectionsManager(_a0 feeds.ConnectionsManager) { - _m.Called(_a0) -} - // UpdateChainConfig provides a mock function with given fields: ctx, cfg func (_m *Service) UpdateChainConfig(ctx context.Context, cfg feeds.ChainConfig) (int64, error) { ret := _m.Called(ctx, cfg) diff --git a/core/services/feeds/orm.go b/core/services/feeds/orm.go index 24ed7b8b369..bf77051dad7 100644 --- a/core/services/feeds/orm.go +++ b/core/services/feeds/orm.go @@ -1,6 +1,7 @@ package feeds import ( + "context" "database/sql" "fmt" "strings" @@ -9,99 +10,104 @@ import ( "github.com/lib/pq" "github.com/pkg/errors" - "github.com/jmoiron/sqlx" - - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" ) //go:generate mockery --with-expecter=true --quiet --name ORM --output ./mocks/ --case=underscore type ORM interface { - CountManagers() (int64, error) - CreateManager(ms *FeedsManager, qopts ...pg.QOpt) (int64, error) - GetManager(id int64) (*FeedsManager, error) - ListManagers() (mgrs []FeedsManager, err error) - ListManagersByIDs(ids []int64) ([]FeedsManager, error) - UpdateManager(mgr FeedsManager, qopts ...pg.QOpt) error - - CreateBatchChainConfig(cfgs []ChainConfig, qopts ...pg.QOpt) ([]int64, error) - CreateChainConfig(cfg ChainConfig, qopts ...pg.QOpt) (int64, error) - DeleteChainConfig(id int64) (int64, error) - GetChainConfig(id int64) (*ChainConfig, error) - ListChainConfigsByManagerIDs(mgrIDs []int64) ([]ChainConfig, error) - UpdateChainConfig(cfg ChainConfig) (int64, error) - - CountJobProposals() (int64, error) - CountJobProposalsByStatus() (counts *JobProposalCounts, err error) - CreateJobProposal(jp *JobProposal) (int64, error) - DeleteProposal(id int64, qopts ...pg.QOpt) error - GetJobProposal(id int64, qopts ...pg.QOpt) (*JobProposal, error) - GetJobProposalByRemoteUUID(uuid uuid.UUID) (*JobProposal, error) - ListJobProposals() (jps []JobProposal, err error) - ListJobProposalsByManagersIDs(ids []int64, qopts ...pg.QOpt) ([]JobProposal, error) - UpdateJobProposalStatus(id int64, status JobProposalStatus, qopts ...pg.QOpt) error // NEEDED? - UpsertJobProposal(jp *JobProposal, qopts ...pg.QOpt) (int64, error) - - ApproveSpec(id int64, externalJobID uuid.UUID, qopts ...pg.QOpt) error - CancelSpec(id int64, qopts ...pg.QOpt) error - CreateSpec(spec JobProposalSpec, qopts ...pg.QOpt) (int64, error) - ExistsSpecByJobProposalIDAndVersion(jpID int64, version int32, qopts ...pg.QOpt) (exists bool, err error) - GetApprovedSpec(jpID int64, qopts ...pg.QOpt) (*JobProposalSpec, error) - GetLatestSpec(jpID int64) (*JobProposalSpec, error) - GetSpec(id int64, qopts ...pg.QOpt) (*JobProposalSpec, error) - ListSpecsByJobProposalIDs(ids []int64, qopts ...pg.QOpt) ([]JobProposalSpec, error) - RejectSpec(id int64, qopts ...pg.QOpt) error - RevokeSpec(id int64, qopts ...pg.QOpt) error - UpdateSpecDefinition(id int64, spec string, qopts ...pg.QOpt) error - - IsJobManaged(jobID int64, qopts ...pg.QOpt) (bool, error) + CountManagers(ctx context.Context) (int64, error) + CreateManager(ctx context.Context, ms *FeedsManager) (int64, error) + GetManager(ctx context.Context, id int64) (*FeedsManager, error) + ListManagers(ctx context.Context) (mgrs []FeedsManager, err error) + ListManagersByIDs(ctx context.Context, ids []int64) ([]FeedsManager, error) + UpdateManager(ctx context.Context, mgr FeedsManager) error + + CreateBatchChainConfig(ctx context.Context, cfgs []ChainConfig) ([]int64, error) + CreateChainConfig(ctx context.Context, cfg ChainConfig) (int64, error) + DeleteChainConfig(ctx context.Context, id int64) (int64, error) + GetChainConfig(ctx context.Context, id int64) (*ChainConfig, error) + ListChainConfigsByManagerIDs(ctx context.Context, mgrIDs []int64) ([]ChainConfig, error) + UpdateChainConfig(ctx context.Context, cfg ChainConfig) (int64, error) + + CountJobProposals(ctx context.Context) (int64, error) + CountJobProposalsByStatus(ctx context.Context) (counts *JobProposalCounts, err error) + CreateJobProposal(ctx context.Context, jp *JobProposal) (int64, error) + DeleteProposal(ctx context.Context, id int64) error + GetJobProposal(ctx context.Context, id int64) (*JobProposal, error) + GetJobProposalByRemoteUUID(ctx context.Context, uuid uuid.UUID) (*JobProposal, error) + ListJobProposals(ctx context.Context) (jps []JobProposal, err error) + ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]JobProposal, error) + UpdateJobProposalStatus(ctx context.Context, id int64, status JobProposalStatus) error // NEEDED? + UpsertJobProposal(ctx context.Context, jp *JobProposal) (int64, error) + + ApproveSpec(ctx context.Context, id int64, externalJobID uuid.UUID) error + CancelSpec(ctx context.Context, id int64) error + CreateSpec(ctx context.Context, spec JobProposalSpec) (int64, error) + ExistsSpecByJobProposalIDAndVersion(ctx context.Context, jpID int64, version int32) (exists bool, err error) + GetApprovedSpec(ctx context.Context, jpID int64) (*JobProposalSpec, error) + GetLatestSpec(ctx context.Context, jpID int64) (*JobProposalSpec, error) + GetSpec(ctx context.Context, id int64) (*JobProposalSpec, error) + ListSpecsByJobProposalIDs(ctx context.Context, ids []int64) ([]JobProposalSpec, error) + RejectSpec(ctx context.Context, id int64) error + RevokeSpec(ctx context.Context, id int64) error + UpdateSpecDefinition(ctx context.Context, id int64, spec string) error + + IsJobManaged(ctx context.Context, jobID int64) (bool, error) + + Transact(context.Context, func(ORM) error) error + WithDataSource(sqlutil.DataSource) ORM } var _ ORM = &orm{} type orm struct { - q pg.Q + ds sqlutil.DataSource } -func NewORM(db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig) *orm { - return &orm{ - q: pg.NewQ(db, lggr, cfg), - } +func NewORM(ds sqlutil.DataSource) *orm { + return &orm{ds: ds} } +func (o *orm) Transact(ctx context.Context, fn func(ORM) error) error { + return sqlutil.Transact(ctx, o.WithDataSource, o.ds, nil, fn) +} + +func (o *orm) WithDataSource(ds sqlutil.DataSource) ORM { return &orm{ds} } + // Count counts the number of feeds manager records. -func (o *orm) CountManagers() (count int64, err error) { +func (o *orm) CountManagers(ctx context.Context) (count int64, err error) { stmt := ` SELECT COUNT(*) FROM feeds_managers ` - err = o.q.Get(&count, stmt) + err = o.ds.GetContext(ctx, &count, stmt) return count, errors.Wrap(err, "CountManagers failed") } // CreateManager creates a feeds manager. -func (o *orm) CreateManager(ms *FeedsManager, qopts ...pg.QOpt) (id int64, err error) { +func (o *orm) CreateManager(ctx context.Context, ms *FeedsManager) (id int64, err error) { stmt := ` INSERT INTO feeds_managers (name, uri, public_key, created_at, updated_at) VALUES ($1,$2,$3,NOW(),NOW()) RETURNING id; ` - err = o.q.WithOpts(qopts...).Get(&id, stmt, ms.Name, ms.URI, ms.PublicKey) + err = o.ds.GetContext(ctx, &id, stmt, ms.Name, ms.URI, ms.PublicKey) return id, errors.Wrap(err, "CreateManager failed") } // CreateChainConfig creates a new chain config. -func (o *orm) CreateChainConfig(cfg ChainConfig, qopts ...pg.QOpt) (id int64, err error) { +func (o *orm) CreateChainConfig(ctx context.Context, cfg ChainConfig) (id int64, err error) { stmt := ` INSERT INTO feeds_manager_chain_configs (feeds_manager_id, chain_id, chain_type, account_address, admin_address, flux_monitor_config, ocr1_config, ocr2_config, created_at, updated_at) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,NOW(),NOW()) RETURNING id; ` - err = o.q.WithOpts(qopts...).Get(&id, + err = o.ds.GetContext(ctx, + &id, stmt, cfg.FeedsManagerID, cfg.ChainID, @@ -117,7 +123,7 @@ RETURNING id; } // CreateBatchChainConfig creates multiple chain configs. -func (o *orm) CreateBatchChainConfig(cfgs []ChainConfig, qopts ...pg.QOpt) (ids []int64, err error) { +func (o *orm) CreateBatchChainConfig(ctx context.Context, cfgs []ChainConfig) (ids []int64, err error) { if len(cfgs) == 0 { return } @@ -160,7 +166,8 @@ RETURNING id; ) } - err = o.q.WithOpts(qopts...).Select(&ids, + err = o.ds.SelectContext(ctx, + &ids, fmt.Sprintf(stmt, strings.Join(vStrs, ",")), vArgs..., ) @@ -169,7 +176,7 @@ RETURNING id; } // DeleteChainConfig deletes a chain config. -func (o *orm) DeleteChainConfig(id int64) (int64, error) { +func (o *orm) DeleteChainConfig(ctx context.Context, id int64) (int64, error) { stmt := ` DELETE FROM feeds_manager_chain_configs WHERE id = $1 @@ -177,13 +184,13 @@ RETURNING id; ` var ccid int64 - err := o.q.Get(&ccid, stmt, id) + err := o.ds.GetContext(ctx, &ccid, stmt, id) return ccid, errors.Wrap(err, "DeleteChainConfig failed") } // GetChainConfig fetches a chain config. -func (o *orm) GetChainConfig(id int64) (*ChainConfig, error) { +func (o *orm) GetChainConfig(ctx context.Context, id int64) (*ChainConfig, error) { stmt := ` SELECT id, feeds_manager_id, chain_id, chain_type, account_address, admin_address, flux_monitor_config, ocr1_config, ocr2_config, created_at, updated_at FROM feeds_manager_chain_configs @@ -191,14 +198,14 @@ WHERE id = $1; ` var cfg ChainConfig - err := o.q.Get(&cfg, stmt, id) + err := o.ds.GetContext(ctx, &cfg, stmt, id) return &cfg, errors.Wrap(err, "GetChainConfig failed") } // ListChainConfigsByManagerIDs fetches the chain configs matching all manager // ids. -func (o *orm) ListChainConfigsByManagerIDs(mgrIDs []int64) ([]ChainConfig, error) { +func (o *orm) ListChainConfigsByManagerIDs(ctx context.Context, mgrIDs []int64) ([]ChainConfig, error) { stmt := ` SELECT id, feeds_manager_id, chain_id, chain_type, account_address, admin_address, flux_monitor_config, ocr1_config, ocr2_config, created_at, updated_at FROM feeds_manager_chain_configs @@ -206,13 +213,13 @@ WHERE feeds_manager_id = ANY($1) ` var cfgs []ChainConfig - err := o.q.Select(&cfgs, stmt, mgrIDs) + err := o.ds.SelectContext(ctx, &cfgs, stmt, mgrIDs) return cfgs, errors.Wrap(err, "ListJobProposalsByManagersIDs failed") } // UpdateChainConfig updates a chain config. -func (o *orm) UpdateChainConfig(cfg ChainConfig) (int64, error) { +func (o *orm) UpdateChainConfig(ctx context.Context, cfg ChainConfig) (int64, error) { stmt := ` UPDATE feeds_manager_chain_configs SET account_address = $1, @@ -226,7 +233,7 @@ RETURNING id; ` var cfgID int64 - err := o.q.Get(&cfgID, stmt, + err := o.ds.GetContext(ctx, &cfgID, stmt, cfg.AccountAddress, cfg.AdminAddress, cfg.FluxMonitorConfig, @@ -239,7 +246,7 @@ RETURNING id; } // GetManager gets a feeds manager by id. -func (o *orm) GetManager(id int64) (mgr *FeedsManager, err error) { +func (o *orm) GetManager(ctx context.Context, id int64) (mgr *FeedsManager, err error) { stmt := ` SELECT id, name, uri, public_key, created_at, updated_at FROM feeds_managers @@ -247,23 +254,23 @@ WHERE id = $1 ` mgr = new(FeedsManager) - err = o.q.Get(mgr, stmt, id) + err = o.ds.GetContext(ctx, mgr, stmt, id) return mgr, errors.Wrap(err, "GetManager failed") } // ListManager lists all feeds managers. -func (o *orm) ListManagers() (mgrs []FeedsManager, err error) { +func (o *orm) ListManagers(ctx context.Context) (mgrs []FeedsManager, err error) { stmt := ` SELECT id, name, uri, public_key, created_at, updated_at FROM feeds_managers; ` - err = o.q.Select(&mgrs, stmt) + err = o.ds.SelectContext(ctx, &mgrs, stmt) return mgrs, errors.Wrap(err, "ListManagers failed") } // ListManagersByIDs gets feeds managers by ids. -func (o *orm) ListManagersByIDs(ids []int64) (managers []FeedsManager, err error) { +func (o *orm) ListManagersByIDs(ctx context.Context, ids []int64) (managers []FeedsManager, err error) { stmt := ` SELECT id, name, uri, public_key, created_at, updated_at FROM feeds_managers @@ -271,20 +278,20 @@ WHERE id = ANY($1) ORDER BY created_at, id;` mgrIds := pq.Array(ids) - err = o.q.Select(&managers, stmt, mgrIds) + err = o.ds.SelectContext(ctx, &managers, stmt, mgrIds) return managers, errors.Wrap(err, "GetManagers failed") } // UpdateManager updates the manager details. -func (o *orm) UpdateManager(mgr FeedsManager, qopts ...pg.QOpt) (err error) { +func (o *orm) UpdateManager(ctx context.Context, mgr FeedsManager) (err error) { stmt := ` UPDATE feeds_managers SET name = $1, uri = $2, public_key = $3, updated_at = NOW() WHERE id = $4; ` - res, err := o.q.WithOpts(qopts...).Exec(stmt, mgr.Name, mgr.URI, mgr.PublicKey, mgr.ID) + res, err := o.ds.ExecContext(ctx, stmt, mgr.Name, mgr.URI, mgr.PublicKey, mgr.ID) if err != nil { return errors.Wrap(err, "UpdateManager failed to update feeds_managers") } @@ -299,27 +306,27 @@ WHERE id = $4; } // CreateJobProposal creates a job proposal. -func (o *orm) CreateJobProposal(jp *JobProposal) (id int64, err error) { +func (o *orm) CreateJobProposal(ctx context.Context, jp *JobProposal) (id int64, err error) { stmt := ` INSERT INTO job_proposals (name, remote_uuid, status, feeds_manager_id, multiaddrs, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, NOW(), NOW()) RETURNING id; ` - err = o.q.Get(&id, stmt, jp.Name, jp.RemoteUUID, jp.Status, jp.FeedsManagerID, jp.Multiaddrs) + err = o.ds.GetContext(ctx, &id, stmt, jp.Name, jp.RemoteUUID, jp.Status, jp.FeedsManagerID, jp.Multiaddrs) return id, errors.Wrap(err, "CreateJobProposal failed") } // CountJobProposals counts the number of job proposal records. -func (o *orm) CountJobProposals() (count int64, err error) { +func (o *orm) CountJobProposals(ctx context.Context) (count int64, err error) { stmt := `SELECT COUNT(*) FROM job_proposals` - err = o.q.Get(&count, stmt) + err = o.ds.GetContext(ctx, &count, stmt) return count, errors.Wrap(err, "CountJobProposals failed") } // CountJobProposals counts the number of job proposal records. -func (o *orm) CountJobProposalsByStatus() (counts *JobProposalCounts, err error) { +func (o *orm) CountJobProposalsByStatus(ctx context.Context) (counts *JobProposalCounts, err error) { stmt := ` SELECT COUNT(*) filter (where job_proposals.status = 'pending' OR job_proposals.pending_update = TRUE) as pending, @@ -332,26 +339,26 @@ FROM job_proposals; ` counts = new(JobProposalCounts) - err = o.q.Get(counts, stmt) + err = o.ds.GetContext(ctx, counts, stmt) return counts, errors.Wrap(err, "CountJobProposalsByStatus failed") } // GetJobProposal gets a job proposal by id. -func (o *orm) GetJobProposal(id int64, qopts ...pg.QOpt) (jp *JobProposal, err error) { +func (o *orm) GetJobProposal(ctx context.Context, id int64) (jp *JobProposal, err error) { stmt := ` SELECT * FROM job_proposals WHERE id = $1 ` jp = new(JobProposal) - err = o.q.WithOpts(qopts...).Get(jp, stmt, id) + err = o.ds.GetContext(ctx, jp, stmt, id) return jp, errors.Wrap(err, "GetJobProposal failed") } // GetJobProposalByRemoteUUID gets a job proposal by the remote FMS uuid. This // method will filter out the deleted job proposals. To get all job proposals, // use the GetJobProposal get by id method. -func (o *orm) GetJobProposalByRemoteUUID(id uuid.UUID) (jp *JobProposal, err error) { +func (o *orm) GetJobProposalByRemoteUUID(ctx context.Context, id uuid.UUID) (jp *JobProposal, err error) { stmt := ` SELECT * FROM job_proposals @@ -360,35 +367,35 @@ AND status <> $2; ` jp = new(JobProposal) - err = o.q.Get(jp, stmt, id, JobProposalStatusDeleted) + err = o.ds.GetContext(ctx, jp, stmt, id, JobProposalStatusDeleted) return jp, errors.Wrap(err, "GetJobProposalByRemoteUUID failed") } // ListJobProposals lists all job proposals. -func (o *orm) ListJobProposals() (jps []JobProposal, err error) { +func (o *orm) ListJobProposals(ctx context.Context) (jps []JobProposal, err error) { stmt := ` SELECT * FROM job_proposals; ` - err = o.q.Select(&jps, stmt) + err = o.ds.SelectContext(ctx, &jps, stmt) return jps, errors.Wrap(err, "ListJobProposals failed") } // ListJobProposalsByManagersIDs gets job proposals by feeds managers IDs. -func (o *orm) ListJobProposalsByManagersIDs(ids []int64, qopts ...pg.QOpt) ([]JobProposal, error) { +func (o *orm) ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]JobProposal, error) { stmt := ` SELECT * FROM job_proposals WHERE feeds_manager_id = ANY($1) ` var jps []JobProposal - err := o.q.WithOpts(qopts...).Select(&jps, stmt, ids) + err := o.ds.SelectContext(ctx, &jps, stmt, ids) return jps, errors.Wrap(err, "ListJobProposalsByManagersIDs failed") } // UpdateJobProposalStatus updates the status of a job proposal by id. -func (o *orm) UpdateJobProposalStatus(id int64, status JobProposalStatus, qopts ...pg.QOpt) error { +func (o *orm) UpdateJobProposalStatus(ctx context.Context, id int64, status JobProposalStatus) error { stmt := ` UPDATE job_proposals SET status = $1, @@ -396,7 +403,7 @@ SET status = $1, WHERE id = $2; ` - result, err := o.q.WithOpts(qopts...).Exec(stmt, status, id) + result, err := o.ds.ExecContext(ctx, stmt, status, id) if err != nil { return err } @@ -415,7 +422,7 @@ WHERE id = $2; // UpsertJobProposal creates a job proposal if it does not exist. If it does exist, // then we update the details of the existing job proposal only if the provided // feeds manager id exists. -func (o *orm) UpsertJobProposal(jp *JobProposal, qopts ...pg.QOpt) (id int64, err error) { +func (o *orm) UpsertJobProposal(ctx context.Context, jp *JobProposal) (id int64, err error) { stmt := ` INSERT INTO job_proposals (name, remote_uuid, status, feeds_manager_id, multiaddrs, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, NOW(), NOW()) @@ -436,13 +443,13 @@ DO RETURNING id; ` - err = o.q.WithOpts(qopts...).Get(&id, stmt, jp.Name, jp.RemoteUUID, jp.Status, jp.FeedsManagerID, jp.Multiaddrs) + err = o.ds.GetContext(ctx, &id, stmt, jp.Name, jp.RemoteUUID, jp.Status, jp.FeedsManagerID, jp.Multiaddrs) return id, errors.Wrap(err, "UpsertJobProposal") } // ApproveSpec approves the spec and sets the external job ID on the associated // job proposal. -func (o *orm) ApproveSpec(id int64, externalJobID uuid.UUID, qopts ...pg.QOpt) error { +func (o *orm) ApproveSpec(ctx context.Context, id int64, externalJobID uuid.UUID) error { // Update the status of the approval stmt := ` UPDATE job_proposal_specs @@ -454,7 +461,7 @@ RETURNING job_proposal_id; ` var jpID int64 - if err := o.q.WithOpts(qopts...).Get(&jpID, stmt, JobProposalStatusApproved, id); err != nil { + if err := o.ds.GetContext(ctx, &jpID, stmt, JobProposalStatusApproved, id); err != nil { return err } @@ -468,7 +475,7 @@ SET status = $1, WHERE id = $3; ` - result, err := o.q.WithOpts(qopts...).Exec(stmt, JobProposalStatusApproved, externalJobID, jpID) + result, err := o.ds.ExecContext(ctx, stmt, JobProposalStatusApproved, externalJobID, jpID) if err != nil { return err } @@ -487,7 +494,7 @@ WHERE id = $3; // CancelSpec cancels the spec and removes the external job id from the associated job proposal. It // sets the status of the spec and the proposal to cancelled, except in the case of deleted // proposals. -func (o *orm) CancelSpec(id int64, qopts ...pg.QOpt) error { +func (o *orm) CancelSpec(ctx context.Context, id int64) error { // Update the status of the approval stmt := ` UPDATE job_proposal_specs @@ -499,7 +506,7 @@ RETURNING job_proposal_id; ` var jpID int64 - if err := o.q.WithOpts(qopts...).Get(&jpID, stmt, SpecStatusCancelled, id); err != nil { + if err := o.ds.GetContext(ctx, &jpID, stmt, SpecStatusCancelled, id); err != nil { return err } @@ -516,7 +523,7 @@ SET status = ( updated_at = NOW() WHERE id = $1; ` - result, err := o.q.WithOpts(qopts...).Exec(stmt, jpID, nil) + result, err := o.ds.ExecContext(ctx, stmt, jpID, nil) if err != nil { return err } @@ -533,7 +540,7 @@ WHERE id = $1; } // CreateSpec creates a new job proposal spec -func (o *orm) CreateSpec(spec JobProposalSpec, qopts ...pg.QOpt) (int64, error) { +func (o *orm) CreateSpec(ctx context.Context, spec JobProposalSpec) (int64, error) { stmt := ` INSERT INTO job_proposal_specs (definition, version, status, job_proposal_id, status_updated_at, created_at, updated_at) VALUES ($1, $2, $3, $4, NOW(), NOW(), NOW()) @@ -541,14 +548,14 @@ RETURNING id; ` var id int64 - err := o.q.WithOpts(qopts...).Get(&id, stmt, spec.Definition, spec.Version, spec.Status, spec.JobProposalID) + err := o.ds.GetContext(ctx, &id, stmt, spec.Definition, spec.Version, spec.Status, spec.JobProposalID) return id, errors.Wrap(err, "CreateJobProposalSpec failed") } // ExistsSpecByJobProposalIDAndVersion checks if a job proposal spec exists for a specific job // proposal and version. -func (o *orm) ExistsSpecByJobProposalIDAndVersion(jpID int64, version int32, qopts ...pg.QOpt) (exists bool, err error) { +func (o *orm) ExistsSpecByJobProposalIDAndVersion(ctx context.Context, jpID int64, version int32) (exists bool, err error) { stmt := ` SELECT exists ( SELECT 1 @@ -557,12 +564,12 @@ SELECT exists ( ); ` - err = o.q.WithOpts(qopts...).Get(&exists, stmt, jpID, version) + err = o.ds.GetContext(ctx, &exists, stmt, jpID, version) return exists, errors.Wrap(err, "JobProposalSpecVersionExists failed") } // DeleteProposal performs a soft delete of the job proposal by setting the status to deleted -func (o *orm) DeleteProposal(id int64, qopts ...pg.QOpt) error { +func (o *orm) DeleteProposal(ctx context.Context, id int64) error { // Get the latest spec for the proposal. stmt := ` SELECT id, definition, version, status, job_proposal_id, status_updated_at, created_at, updated_at @@ -577,7 +584,7 @@ AND job_proposal_id = $1 ` var spec JobProposalSpec - err := o.q.WithOpts(qopts...).Get(&spec, stmt, id) + err := o.ds.GetContext(ctx, &spec, stmt, id) if err != nil { return err } @@ -593,7 +600,7 @@ SET status = $1, WHERE id = $2; ` - result, err := o.q.WithOpts(qopts...).Exec(stmt, JobProposalStatusDeleted, id, pendingUpdate) + result, err := o.ds.ExecContext(ctx, stmt, JobProposalStatusDeleted, id, pendingUpdate) if err != nil { return err } @@ -610,20 +617,20 @@ WHERE id = $2; } // GetSpec fetches the job proposal spec by id -func (o *orm) GetSpec(id int64, qopts ...pg.QOpt) (*JobProposalSpec, error) { +func (o *orm) GetSpec(ctx context.Context, id int64) (*JobProposalSpec, error) { stmt := ` SELECT id, definition, version, status, job_proposal_id, status_updated_at, created_at, updated_at FROM job_proposal_specs WHERE id = $1; ` var spec JobProposalSpec - err := o.q.WithOpts(qopts...).Get(&spec, stmt, id) + err := o.ds.GetContext(ctx, &spec, stmt, id) return &spec, errors.Wrap(err, "CreateJobProposalSpec failed") } // GetApprovedSpec gets the approved spec for a job proposal -func (o *orm) GetApprovedSpec(jpID int64, qopts ...pg.QOpt) (*JobProposalSpec, error) { +func (o *orm) GetApprovedSpec(ctx context.Context, jpID int64) (*JobProposalSpec, error) { stmt := ` SELECT id, definition, version, status, job_proposal_id, status_updated_at, created_at, updated_at FROM job_proposal_specs @@ -632,13 +639,13 @@ AND job_proposal_id = $2 ` var spec JobProposalSpec - err := o.q.WithOpts(qopts...).Get(&spec, stmt, SpecStatusApproved, jpID) + err := o.ds.GetContext(ctx, &spec, stmt, SpecStatusApproved, jpID) return &spec, errors.Wrap(err, "GetApprovedSpec failed") } // GetLatestSpec gets the latest spec for a job proposal. -func (o *orm) GetLatestSpec(jpID int64) (*JobProposalSpec, error) { +func (o *orm) GetLatestSpec(ctx context.Context, jpID int64) (*JobProposalSpec, error) { stmt := ` SELECT id, definition, version, status, job_proposal_id, status_updated_at, created_at, updated_at FROM job_proposal_specs @@ -652,26 +659,26 @@ AND job_proposal_id = $1 ` var spec JobProposalSpec - err := o.q.Get(&spec, stmt, jpID) + err := o.ds.GetContext(ctx, &spec, stmt, jpID) return &spec, errors.Wrap(err, "GetLatestSpec failed") } // ListSpecsByJobProposalIDs lists the specs which belong to any of job proposal // ids. -func (o *orm) ListSpecsByJobProposalIDs(ids []int64, qopts ...pg.QOpt) ([]JobProposalSpec, error) { +func (o *orm) ListSpecsByJobProposalIDs(ctx context.Context, ids []int64) ([]JobProposalSpec, error) { stmt := ` SELECT id, definition, version, status, job_proposal_id, status_updated_at, created_at, updated_at FROM job_proposal_specs WHERE job_proposal_id = ANY($1) ` var specs []JobProposalSpec - err := o.q.WithOpts(qopts...).Select(&specs, stmt, ids) + err := o.ds.SelectContext(ctx, &specs, stmt, ids) return specs, errors.Wrap(err, "GetJobProposalsByManagersIDs failed") } // RejectSpec rejects the spec and updates the job proposal -func (o *orm) RejectSpec(id int64, qopts ...pg.QOpt) error { +func (o *orm) RejectSpec(ctx context.Context, id int64) error { stmt := ` UPDATE job_proposal_specs SET status = $1, @@ -682,7 +689,7 @@ RETURNING job_proposal_id; ` var jpID int64 - if err := o.q.WithOpts(qopts...).Get(&jpID, stmt, SpecStatusRejected, id); err != nil { + if err := o.ds.GetContext(ctx, &jpID, stmt, SpecStatusRejected, id); err != nil { return err } @@ -700,7 +707,7 @@ SET status = ( WHERE id = $1 ` - result, err := o.q.WithOpts(qopts...).Exec(stmt, jpID) + result, err := o.ds.ExecContext(ctx, stmt, jpID) if err != nil { return err } @@ -719,7 +726,7 @@ WHERE id = $1 // RevokeSpec revokes a job proposal with a pending job spec. An approved // proposal cannot be revoked. A revoked proposal's job spec cannot be approved // or edited, but the job can be reproposed by FMS. -func (o *orm) RevokeSpec(id int64, qopts ...pg.QOpt) error { +func (o *orm) RevokeSpec(ctx context.Context, id int64) error { // Update the status of the spec stmt := ` UPDATE job_proposal_specs @@ -736,7 +743,7 @@ RETURNING job_proposal_id; ` var jpID int64 - if err := o.q.WithOpts(qopts...).Get(&jpID, stmt, id, SpecStatusRevoked); err != nil { + if err := o.ds.GetContext(ctx, &jpID, stmt, id, SpecStatusRevoked); err != nil { return err } @@ -760,7 +767,7 @@ SET status = ( WHERE id = $1 ` - result, err := o.q.WithOpts(qopts...).Exec(stmt, jpID, nil, JobProposalStatusRevoked) + result, err := o.ds.ExecContext(ctx, stmt, jpID, nil, JobProposalStatusRevoked) if err != nil { return err } @@ -777,7 +784,7 @@ WHERE id = $1 } // UpdateSpecDefinition updates the definition of a job proposal spec by id. -func (o *orm) UpdateSpecDefinition(id int64, spec string, qopts ...pg.QOpt) error { +func (o *orm) UpdateSpecDefinition(ctx context.Context, id int64, spec string) error { stmt := ` UPDATE job_proposal_specs SET definition = $1, @@ -785,7 +792,7 @@ SET definition = $1, WHERE id = $2; ` - res, err := o.q.WithOpts(qopts...).Exec(stmt, spec, id) + res, err := o.ds.ExecContext(ctx, stmt, spec, id) if err != nil { return errors.Wrap(err, "UpdateSpecDefinition failed to update definition") } @@ -803,7 +810,7 @@ WHERE id = $2; } // IsJobManaged determines if a job is managed by the feeds manager. -func (o *orm) IsJobManaged(jobID int64, qopts ...pg.QOpt) (exists bool, err error) { +func (o *orm) IsJobManaged(ctx context.Context, jobID int64) (exists bool, err error) { stmt := ` SELECT exists ( SELECT 1 @@ -813,6 +820,6 @@ SELECT exists ( ); ` - err = o.q.WithOpts(qopts...).Get(&exists, stmt, jobID) + err = o.ds.GetContext(ctx, &exists, stmt, jobID) return exists, errors.Wrap(err, "IsJobManaged failed") } diff --git a/core/services/feeds/orm_test.go b/core/services/feeds/orm_test.go index 3a0a17c99e0..df2624319f5 100644 --- a/core/services/feeds/orm_test.go +++ b/core/services/feeds/orm_test.go @@ -5,13 +5,12 @@ import ( "testing" "github.com/google/uuid" + "github.com/jmoiron/sqlx" "github.com/lib/pq" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gopkg.in/guregu/null.v4" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" @@ -45,9 +44,8 @@ func setupORM(t *testing.T) *TestORM { t.Helper() var ( - db = pgtest.NewSqlxDB(t) - lggr = logger.TestLogger(t) - orm = feeds.NewORM(db, lggr, pgtest.NewQConfig(true)) + db = pgtest.NewSqlxDB(t) + orm = feeds.NewORM(db) ) return &TestORM{ORM: orm, db: db} @@ -57,6 +55,7 @@ func setupORM(t *testing.T) *TestORM { func Test_ORM_CreateManager(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -67,14 +66,14 @@ func Test_ORM_CreateManager(t *testing.T) { } ) - count, err := orm.CountManagers() + count, err := orm.CountManagers(ctx) require.NoError(t, err) require.Equal(t, int64(0), count) - id, err := orm.CreateManager(mgr) + id, err := orm.CreateManager(ctx, mgr) require.NoError(t, err) - count, err = orm.CountManagers() + count, err = orm.CountManagers(ctx) require.NoError(t, err) require.Equal(t, int64(1), count) @@ -83,6 +82,7 @@ func Test_ORM_CreateManager(t *testing.T) { func Test_ORM_GetManager(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -93,10 +93,10 @@ func Test_ORM_GetManager(t *testing.T) { } ) - id, err := orm.CreateManager(mgr) + id, err := orm.CreateManager(ctx, mgr) require.NoError(t, err) - actual, err := orm.GetManager(id) + actual, err := orm.GetManager(ctx, id) require.NoError(t, err) assert.Equal(t, id, actual.ID) @@ -104,12 +104,13 @@ func Test_ORM_GetManager(t *testing.T) { assert.Equal(t, name, actual.Name) assert.Equal(t, publicKey, actual.PublicKey) - _, err = orm.GetManager(-1) + _, err = orm.GetManager(ctx, -1) require.Error(t, err) } func Test_ORM_ListManagers(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -120,10 +121,10 @@ func Test_ORM_ListManagers(t *testing.T) { } ) - id, err := orm.CreateManager(mgr) + id, err := orm.CreateManager(ctx, mgr) require.NoError(t, err) - mgrs, err := orm.ListManagers() + mgrs, err := orm.ListManagers(ctx) require.NoError(t, err) require.Len(t, mgrs, 1) @@ -136,6 +137,7 @@ func Test_ORM_ListManagers(t *testing.T) { func Test_ORM_ListManagersByIDs(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -146,10 +148,10 @@ func Test_ORM_ListManagersByIDs(t *testing.T) { } ) - id, err := orm.CreateManager(mgr) + id, err := orm.CreateManager(ctx, mgr) require.NoError(t, err) - mgrs, err := orm.ListManagersByIDs([]int64{id}) + mgrs, err := orm.ListManagersByIDs(ctx, []int64{id}) require.NoError(t, err) require.Equal(t, 1, len(mgrs)) @@ -162,6 +164,7 @@ func Test_ORM_ListManagersByIDs(t *testing.T) { func Test_ORM_UpdateManager(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -172,7 +175,7 @@ func Test_ORM_UpdateManager(t *testing.T) { } ) - id, err := orm.CreateManager(mgr) + id, err := orm.CreateManager(ctx, mgr) require.NoError(t, err) updatedMgr := feeds.FeedsManager{ @@ -182,10 +185,10 @@ func Test_ORM_UpdateManager(t *testing.T) { PublicKey: crypto.PublicKey([]byte("22222222222222222222222222222222")), } - err = orm.UpdateManager(updatedMgr) + err = orm.UpdateManager(ctx, updatedMgr) require.NoError(t, err) - actual, err := orm.GetManager(id) + actual, err := orm.GetManager(ctx, id) require.NoError(t, err) assert.Equal(t, updatedMgr.URI, actual.URI) @@ -197,6 +200,7 @@ func Test_ORM_UpdateManager(t *testing.T) { func Test_ORM_CreateChainConfig(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -224,10 +228,10 @@ func Test_ORM_CreateChainConfig(t *testing.T) { } ) - id, err := orm.CreateChainConfig(cfg1) + id, err := orm.CreateChainConfig(ctx, cfg1) require.NoError(t, err) - actual, err := orm.GetChainConfig(id) + actual, err := orm.GetChainConfig(ctx, id) require.NoError(t, err) assertChainConfigEqual(t, map[string]interface{}{ @@ -244,6 +248,7 @@ func Test_ORM_CreateChainConfig(t *testing.T) { func Test_ORM_CreateBatchChainConfig(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -264,12 +269,12 @@ func Test_ORM_CreateBatchChainConfig(t *testing.T) { } ) - ids, err := orm.CreateBatchChainConfig([]feeds.ChainConfig{cfg1, cfg2}) + ids, err := orm.CreateBatchChainConfig(ctx, []feeds.ChainConfig{cfg1, cfg2}) require.NoError(t, err) assert.Len(t, ids, 2) - actual, err := orm.GetChainConfig(ids[0]) + actual, err := orm.GetChainConfig(ctx, ids[0]) require.NoError(t, err) assertChainConfigEqual(t, map[string]interface{}{ @@ -283,7 +288,7 @@ func Test_ORM_CreateBatchChainConfig(t *testing.T) { "ocr2Config": cfg1.OCR2Config, }, *actual) - actual, err = orm.GetChainConfig(ids[1]) + actual, err = orm.GetChainConfig(ctx, ids[1]) require.NoError(t, err) assertChainConfigEqual(t, map[string]interface{}{ @@ -298,13 +303,14 @@ func Test_ORM_CreateBatchChainConfig(t *testing.T) { }, *actual) // Test empty configs - ids, err = orm.CreateBatchChainConfig([]feeds.ChainConfig{}) + ids, err = orm.CreateBatchChainConfig(ctx, []feeds.ChainConfig{}) require.NoError(t, err) require.Empty(t, ids) } func Test_ORM_DeleteChainConfig(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -318,22 +324,23 @@ func Test_ORM_DeleteChainConfig(t *testing.T) { } ) - id, err := orm.CreateChainConfig(cfg1) + id, err := orm.CreateChainConfig(ctx, cfg1) require.NoError(t, err) - _, err = orm.GetChainConfig(id) + _, err = orm.GetChainConfig(ctx, id) require.NoError(t, err) - actual, err := orm.DeleteChainConfig(id) + actual, err := orm.DeleteChainConfig(ctx, id) require.NoError(t, err) require.Equal(t, id, actual) - _, err = orm.GetChainConfig(id) + _, err = orm.GetChainConfig(ctx, id) require.Error(t, err) } func Test_ORM_ListChainConfigsByManagerIDs(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -361,10 +368,10 @@ func Test_ORM_ListChainConfigsByManagerIDs(t *testing.T) { } ) - _, err := orm.CreateChainConfig(cfg1) + _, err := orm.CreateChainConfig(ctx, cfg1) require.NoError(t, err) - actual, err := orm.ListChainConfigsByManagerIDs([]int64{fmID}) + actual, err := orm.ListChainConfigsByManagerIDs(ctx, []int64{fmID}) require.NoError(t, err) require.Len(t, actual, 1) @@ -382,6 +389,7 @@ func Test_ORM_ListChainConfigsByManagerIDs(t *testing.T) { func Test_ORM_UpdateChainConfig(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -414,15 +422,15 @@ func Test_ORM_UpdateChainConfig(t *testing.T) { } ) - id, err := orm.CreateChainConfig(cfg1) + id, err := orm.CreateChainConfig(ctx, cfg1) require.NoError(t, err) updateCfg.ID = id - id, err = orm.UpdateChainConfig(updateCfg) + id, err = orm.UpdateChainConfig(ctx, updateCfg) require.NoError(t, err) - actual, err := orm.GetChainConfig(id) + actual, err := orm.GetChainConfig(ctx, id) require.NoError(t, err) assertChainConfigEqual(t, map[string]interface{}{ @@ -441,6 +449,7 @@ func Test_ORM_UpdateChainConfig(t *testing.T) { func Test_ORM_CreateJobProposal(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) orm := setupORM(t) fmID := createFeedsManager(t, orm) @@ -452,14 +461,14 @@ func Test_ORM_CreateJobProposal(t *testing.T) { FeedsManagerID: fmID, } - count, err := orm.CountJobProposals() + count, err := orm.CountJobProposals(ctx) require.NoError(t, err) require.Equal(t, int64(0), count) - id, err := orm.CreateJobProposal(jp) + id, err := orm.CreateJobProposal(ctx, jp) require.NoError(t, err) - actual, err := orm.GetJobProposal(id) + actual, err := orm.GetJobProposal(ctx, id) require.NoError(t, err) require.Equal(t, jp.Name, actual.Name) require.Equal(t, jp.RemoteUUID, actual.RemoteUUID) @@ -474,6 +483,7 @@ func Test_ORM_CreateJobProposal(t *testing.T) { func Test_ORM_GetJobProposal(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) orm := setupORM(t) fmID := createFeedsManager(t, orm) @@ -495,10 +505,10 @@ func Test_ORM_GetJobProposal(t *testing.T) { FeedsManagerID: fmID, } - id, err := orm.CreateJobProposal(jp) + id, err := orm.CreateJobProposal(ctx, jp) require.NoError(t, err) - _, err = orm.CreateJobProposal(deletedJp) + _, err = orm.CreateJobProposal(ctx, deletedJp) require.NoError(t, err) assertJobEquals := func(actual *feeds.JobProposal) { @@ -512,32 +522,33 @@ func Test_ORM_GetJobProposal(t *testing.T) { } t.Run("by id", func(t *testing.T) { - actual, err := orm.GetJobProposal(id) + actual, err := orm.GetJobProposal(ctx, id) require.NoError(t, err) assert.Equal(t, id, actual.ID) assertJobEquals(actual) - _, err = orm.GetJobProposal(int64(0)) + _, err = orm.GetJobProposal(ctx, int64(0)) require.Error(t, err) }) t.Run("by remote uuid", func(t *testing.T) { - actual, err := orm.GetJobProposalByRemoteUUID(remoteUUID) + actual, err := orm.GetJobProposalByRemoteUUID(ctx, remoteUUID) require.NoError(t, err) assertJobEquals(actual) - _, err = orm.GetJobProposalByRemoteUUID(deletedUUID) + _, err = orm.GetJobProposalByRemoteUUID(ctx, deletedUUID) require.Error(t, err) - _, err = orm.GetJobProposalByRemoteUUID(uuid.New()) + _, err = orm.GetJobProposalByRemoteUUID(ctx, uuid.New()) require.Error(t, err) }) } func Test_ORM_ListJobProposals(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) orm := setupORM(t) fmID := createFeedsManager(t, orm) @@ -551,10 +562,10 @@ func Test_ORM_ListJobProposals(t *testing.T) { FeedsManagerID: fmID, } - id, err := orm.CreateJobProposal(jp) + id, err := orm.CreateJobProposal(ctx, jp) require.NoError(t, err) - jps, err := orm.ListJobProposals() + jps, err := orm.ListJobProposals(ctx) require.NoError(t, err) require.Len(t, jps, 1) @@ -573,13 +584,14 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { testCases := []struct { name string - before func(orm *TestORM) *feeds.JobProposalCounts + before func(t *testing.T, orm *TestORM) *feeds.JobProposalCounts wantApproved, wantRejected, wantDeleted, wantRevoked, wantPending, wantCancelled int64 }{ { name: "correctly counts when there are no job proposals", - before: func(orm *TestORM) *feeds.JobProposalCounts { - counts, err := orm.CountJobProposalsByStatus() + before: func(t *testing.T, orm *TestORM) *feeds.JobProposalCounts { + ctx := testutils.Context(t) + counts, err := orm.CountJobProposalsByStatus(ctx) require.NoError(t, err) return counts @@ -587,12 +599,13 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { }, { name: "correctly counts a pending and cancelled job proposal by status", - before: func(orm *TestORM) *feeds.JobProposalCounts { + before: func(t *testing.T, orm *TestORM) *feeds.JobProposalCounts { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) createJobProposal(t, orm, feeds.JobProposalStatusCancelled, fmID) - counts, err := orm.CountJobProposalsByStatus() + counts, err := orm.CountJobProposalsByStatus(ctx) require.NoError(t, err) return counts @@ -604,12 +617,13 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { // Verify that the counts are correct even if the proposal status is not pending. A // spec is considered pending if its status is pending OR pending_update is TRUE name: "correctly counts the pending specs when pending_update is true but the status itself is not pending", - before: func(orm *TestORM) *feeds.JobProposalCounts { + before: func(t *testing.T, orm *TestORM) *feeds.JobProposalCounts { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) // Create a pending job proposal. jUUID := uuid.New() - jpID, err := orm.CreateJobProposal(&feeds.JobProposal{ + jpID, err := orm.CreateJobProposal(ctx, &feeds.JobProposal{ RemoteUUID: jUUID, Status: feeds.JobProposalStatusPending, FeedsManagerID: fmID, @@ -617,7 +631,7 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { require.NoError(t, err) // Upsert the proposal and change its status to rejected - _, err = orm.UpsertJobProposal(&feeds.JobProposal{ + _, err = orm.UpsertJobProposal(ctx, &feeds.JobProposal{ RemoteUUID: jUUID, Status: feeds.JobProposalStatusRejected, FeedsManagerID: fmID, @@ -625,11 +639,11 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { require.NoError(t, err) // Assert that the upserted job proposal is now pending update. - jp, err := orm.GetJobProposal(jpID) + jp, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, true, jp.PendingUpdate) - counts, err := orm.CountJobProposalsByStatus() + counts, err := orm.CountJobProposalsByStatus(ctx) require.NoError(t, err) return counts @@ -638,7 +652,8 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { }, { name: "correctly counts when approving a job proposal", - before: func(orm *TestORM) *feeds.JobProposalCounts { + before: func(t *testing.T, orm *TestORM) *feeds.JobProposalCounts { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) // Create a pending job proposal. @@ -649,15 +664,15 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { specID := createJobSpec(t, orm, jpID) // Defer the FK requirement of an existing job for a job proposal to be approved - require.NoError(t, utils.JustError(orm.db.Exec( + require.NoError(t, utils.JustError(orm.db.ExecContext(ctx, `SET CONSTRAINTS job_proposals_job_id_fkey DEFERRED`, ))) // Approve the pending job proposal. - err := orm.ApproveSpec(specID, jUUID) + err := orm.ApproveSpec(ctx, specID, jUUID) require.NoError(t, err) - counts, err := orm.CountJobProposalsByStatus() + counts, err := orm.CountJobProposalsByStatus(ctx) require.NoError(t, err) return counts @@ -666,16 +681,17 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { }, { name: "correctly counts when revoking a job proposal", - before: func(orm *TestORM) *feeds.JobProposalCounts { + before: func(t *testing.T, orm *TestORM) *feeds.JobProposalCounts { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) specID := createJobSpec(t, orm, jpID) // Revoke the pending job proposal. - err := orm.RevokeSpec(specID) + err := orm.RevokeSpec(ctx, specID) require.NoError(t, err) - counts, err := orm.CountJobProposalsByStatus() + counts, err := orm.CountJobProposalsByStatus(ctx) require.NoError(t, err) return counts @@ -684,16 +700,17 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { }, { name: "correctly counts when deleting a job proposal", - before: func(orm *TestORM) *feeds.JobProposalCounts { + before: func(t *testing.T, orm *TestORM) *feeds.JobProposalCounts { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) createJobSpec(t, orm, jpID) // Delete the pending job proposal. - err := orm.DeleteProposal(jpID) + err := orm.DeleteProposal(ctx, jpID) require.NoError(t, err) - counts, err := orm.CountJobProposalsByStatus() + counts, err := orm.CountJobProposalsByStatus(ctx) require.NoError(t, err) return counts @@ -702,12 +719,13 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { }, { name: "correctly counts when deleting a job proposal with an approved spec", - before: func(orm *TestORM) *feeds.JobProposalCounts { + before: func(t *testing.T, orm *TestORM) *feeds.JobProposalCounts { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) // Create a pending job proposal. jUUID := uuid.New() - jpID, err := orm.CreateJobProposal(&feeds.JobProposal{ + jpID, err := orm.CreateJobProposal(ctx, &feeds.JobProposal{ RemoteUUID: jUUID, Status: feeds.JobProposalStatusPending, FeedsManagerID: fmID, @@ -719,18 +737,18 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { specID := createJobSpec(t, orm, jpID) // Defer the FK requirement of an existing job for a job proposal to be approved - require.NoError(t, utils.JustError(orm.db.Exec( + require.NoError(t, utils.JustError(orm.db.ExecContext(ctx, `SET CONSTRAINTS job_proposals_job_id_fkey DEFERRED`, ))) - err = orm.ApproveSpec(specID, jUUID) + err = orm.ApproveSpec(ctx, specID, jUUID) require.NoError(t, err) // Delete the pending job proposal. - err = orm.DeleteProposal(jpID) + err = orm.DeleteProposal(ctx, jpID) require.NoError(t, err) - counts, err := orm.CountJobProposalsByStatus() + counts, err := orm.CountJobProposalsByStatus(ctx) require.NoError(t, err) return counts @@ -745,7 +763,7 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { t.Run(tc.name, func(t *testing.T) { orm := setupORM(t) - counts := tc.before(orm) + counts := tc.before(t, orm) assert.Equal(t, tc.wantPending, counts.Pending) assert.Equal(t, tc.wantApproved, counts.Approved) @@ -759,6 +777,7 @@ func Test_ORM_CountJobProposalsByStatus(t *testing.T) { func Test_ORM_ListJobProposalByManagersIDs(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) orm := setupORM(t) fmID := createFeedsManager(t, orm) @@ -772,10 +791,10 @@ func Test_ORM_ListJobProposalByManagersIDs(t *testing.T) { FeedsManagerID: fmID, } - id, err := orm.CreateJobProposal(jp) + id, err := orm.CreateJobProposal(ctx, jp) require.NoError(t, err) - jps, err := orm.ListJobProposalsByManagersIDs([]int64{fmID}) + jps, err := orm.ListJobProposalsByManagersIDs(ctx, []int64{fmID}) require.NoError(t, err) require.Len(t, jps, 1) @@ -791,18 +810,19 @@ func Test_ORM_ListJobProposalByManagersIDs(t *testing.T) { func Test_ORM_UpdateJobProposalStatus(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) orm := setupORM(t) fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) - actualCreated, err := orm.GetJobProposal(jpID) + actualCreated, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) - err = orm.UpdateJobProposalStatus(jpID, feeds.JobProposalStatusRejected) + err = orm.UpdateJobProposalStatus(ctx, jpID, feeds.JobProposalStatusRejected) require.NoError(t, err) - actual, err := orm.GetJobProposal(jpID) + actual, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, jpID, actual.ID) @@ -812,6 +832,7 @@ func Test_ORM_UpdateJobProposalStatus(t *testing.T) { func Test_ORM_UpsertJobProposal(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -833,19 +854,19 @@ func Test_ORM_UpsertJobProposal(t *testing.T) { // from pending to approved, and then approved to pending, and pending to deleted and so forth. // Create - count, err := orm.CountJobProposals() + count, err := orm.CountJobProposals(ctx) require.NoError(t, err) require.Equal(t, int64(0), count) - jpID, err := orm.UpsertJobProposal(jp) + jpID, err := orm.UpsertJobProposal(ctx, jp) require.NoError(t, err) - createdActual, err := orm.GetJobProposal(jpID) + createdActual, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.False(t, createdActual.PendingUpdate) - count, err = orm.CountJobProposals() + count, err = orm.CountJobProposals(ctx) require.NoError(t, err) require.Equal(t, int64(1), count) @@ -855,10 +876,10 @@ func Test_ORM_UpsertJobProposal(t *testing.T) { jp.Multiaddrs = pq.StringArray{"dns/example.com"} jp.Name = null.StringFrom("jp1_updated") - jpID, err = orm.UpsertJobProposal(jp) + jpID, err = orm.UpsertJobProposal(ctx, jp) require.NoError(t, err) - actual, err := orm.GetJobProposal(jpID) + actual, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, jp.Name, actual.Name) assert.Equal(t, jp.Status, actual.Status) @@ -874,14 +895,14 @@ func Test_ORM_UpsertJobProposal(t *testing.T) { specID := createJobSpec(t, orm, jpID) // Defer the FK requirement of an existing job for a job proposal. - require.NoError(t, utils.JustError(orm.db.Exec( + require.NoError(t, utils.JustError(orm.db.ExecContext(ctx, `SET CONSTRAINTS job_proposals_job_id_fkey DEFERRED`, ))) - err = orm.ApproveSpec(specID, externalJobID.UUID) + err = orm.ApproveSpec(ctx, specID, externalJobID.UUID) require.NoError(t, err) - actual, err = orm.GetJobProposal(jpID) + actual, err = orm.GetJobProposal(ctx, jpID) require.NoError(t, err) // Assert that the job proposal is now approved. @@ -893,10 +914,10 @@ func Test_ORM_UpsertJobProposal(t *testing.T) { jp.Name = null.StringFrom("jp1_updated_again") jp.Status = feeds.JobProposalStatusPending - _, err = orm.UpsertJobProposal(jp) + _, err = orm.UpsertJobProposal(ctx, jp) require.NoError(t, err) - actual, err = orm.GetJobProposal(jpID) + actual, err = orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, feeds.JobProposalStatusApproved, actual.Status) @@ -904,10 +925,10 @@ func Test_ORM_UpsertJobProposal(t *testing.T) { assert.True(t, actual.PendingUpdate) // Delete the proposal - err = orm.DeleteProposal(jpID) + err = orm.DeleteProposal(ctx, jpID) require.NoError(t, err) - actual, err = orm.GetJobProposal(jpID) + actual, err = orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, feeds.JobProposalStatusDeleted, actual.Status) @@ -915,11 +936,11 @@ func Test_ORM_UpsertJobProposal(t *testing.T) { // Update deleted proposal jp.Status = feeds.JobProposalStatusRejected - jpID, err = orm.UpsertJobProposal(jp) + jpID, err = orm.UpsertJobProposal(ctx, jp) require.NoError(t, err) // Ensure the deleted proposal does not get updated - actual, err = orm.GetJobProposal(jpID) + actual, err = orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.NotEqual(t, jp.Status, actual.Status) assert.Equal(t, feeds.JobProposalStatusDeleted, actual.Status) @@ -929,6 +950,7 @@ func Test_ORM_UpsertJobProposal(t *testing.T) { func Test_ORM_ApproveSpec(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -937,7 +959,7 @@ func Test_ORM_ApproveSpec(t *testing.T) { ) // Manually create the job proposal to set pending update - jpID, err := orm.CreateJobProposal(&feeds.JobProposal{ + jpID, err := orm.CreateJobProposal(ctx, &feeds.JobProposal{ RemoteUUID: uuid.New(), Status: feeds.JobProposalStatusPending, FeedsManagerID: fmID, @@ -947,20 +969,20 @@ func Test_ORM_ApproveSpec(t *testing.T) { specID := createJobSpec(t, orm, jpID) // Defer the FK requirement of an existing job for a job proposal. - require.NoError(t, utils.JustError(orm.db.Exec( + require.NoError(t, utils.JustError(orm.db.ExecContext(ctx, `SET CONSTRAINTS job_proposals_job_id_fkey DEFERRED`, ))) - err = orm.ApproveSpec(specID, externalJobID.UUID) + err = orm.ApproveSpec(ctx, specID, externalJobID.UUID) require.NoError(t, err) - actual, err := orm.GetSpec(specID) + actual, err := orm.GetSpec(ctx, specID) require.NoError(t, err) assert.Equal(t, specID, actual.ID) assert.Equal(t, feeds.SpecStatusApproved, actual.Status) - actualJP, err := orm.GetJobProposal(jpID) + actualJP, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, externalJobID, actualJP.ExternalJobID) @@ -973,14 +995,14 @@ func Test_ORM_CancelSpec(t *testing.T) { testCases := []struct { name string - before func(orm *TestORM) (int64, int64) + before func(t *testing.T, orm *TestORM) (int64, int64) wantSpecStatus feeds.SpecStatus wantProposalStatus feeds.JobProposalStatus wantErr string }{ { name: "pending proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) specID := createJobSpec(t, orm, jpID) @@ -992,7 +1014,7 @@ func Test_ORM_CancelSpec(t *testing.T) { }, { name: "deleted proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusDeleted, fmID) specID := createJobSpec(t, orm, jpID) @@ -1004,7 +1026,7 @@ func Test_ORM_CancelSpec(t *testing.T) { }, { name: "not found", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { return 0, 0 }, wantErr: "sql: no rows in result set", @@ -1015,24 +1037,25 @@ func Test_ORM_CancelSpec(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { + ctx := testutils.Context(t) orm := setupORM(t) - jpID, specID := tc.before(orm) + jpID, specID := tc.before(t, orm) - err := orm.CancelSpec(specID) + err := orm.CancelSpec(ctx, specID) if tc.wantErr != "" { require.EqualError(t, err, tc.wantErr) } else { require.NoError(t, err) - actual, err := orm.GetSpec(specID) + actual, err := orm.GetSpec(ctx, specID) require.NoError(t, err) assert.Equal(t, specID, actual.ID) assert.Equal(t, tc.wantSpecStatus, actual.Status) - actualJP, err := orm.GetJobProposal(jpID) + actualJP, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, tc.wantProposalStatus, actualJP.Status) @@ -1047,14 +1070,14 @@ func Test_ORM_DeleteProposal(t *testing.T) { testCases := []struct { name string - before func(orm *TestORM) int64 + before func(t *testing.T, orm *TestORM) int64 wantProposalStatus feeds.JobProposalStatus wantProposalPendingUpdate bool wantErr string }{ { name: "pending proposal", - before: func(orm *TestORM) int64 { + before: func(t *testing.T, orm *TestORM) int64 { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) createJobSpec(t, orm, jpID) @@ -1066,7 +1089,8 @@ func Test_ORM_DeleteProposal(t *testing.T) { }, { name: "approved proposal with approved spec", - before: func(orm *TestORM) int64 { + before: func(t *testing.T, orm *TestORM) int64 { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) specID := createJobSpec(t, orm, jpID) @@ -1074,11 +1098,11 @@ func Test_ORM_DeleteProposal(t *testing.T) { externalJobID := uuid.NullUUID{UUID: uuid.New(), Valid: true} // Defer the FK requirement of an existing job for a job proposal. - require.NoError(t, utils.JustError(orm.db.Exec( + require.NoError(t, utils.JustError(orm.db.ExecContext(ctx, `SET CONSTRAINTS job_proposals_job_id_fkey DEFERRED`, ))) - err := orm.ApproveSpec(specID, externalJobID.UUID) + err := orm.ApproveSpec(ctx, specID, externalJobID.UUID) require.NoError(t, err) return jpID @@ -1088,7 +1112,8 @@ func Test_ORM_DeleteProposal(t *testing.T) { }, { name: "approved proposal with pending spec", - before: func(orm *TestORM) int64 { + before: func(t *testing.T, orm *TestORM) int64 { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) specID := createJobSpec(t, orm, jpID) @@ -1096,25 +1121,25 @@ func Test_ORM_DeleteProposal(t *testing.T) { externalJobID := uuid.NullUUID{UUID: uuid.New(), Valid: true} // Defer the FK requirement of an existing job for a job proposal. - require.NoError(t, utils.JustError(orm.db.Exec( + require.NoError(t, utils.JustError(orm.db.ExecContext(ctx, `SET CONSTRAINTS job_proposals_job_id_fkey DEFERRED`, ))) - err := orm.ApproveSpec(specID, externalJobID.UUID) + err := orm.ApproveSpec(ctx, specID, externalJobID.UUID) require.NoError(t, err) - jp, err := orm.GetJobProposal(jpID) + jp, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) // Update the proposal to pending and create a new pending spec - _, err = orm.UpsertJobProposal(&feeds.JobProposal{ + _, err = orm.UpsertJobProposal(ctx, &feeds.JobProposal{ RemoteUUID: jp.RemoteUUID, Status: feeds.JobProposalStatusPending, FeedsManagerID: fmID, }) require.NoError(t, err) - _, err = orm.CreateSpec(feeds.JobProposalSpec{ + _, err = orm.CreateSpec(ctx, feeds.JobProposalSpec{ Definition: "spec data", Version: 2, Status: feeds.SpecStatusPending, @@ -1129,7 +1154,7 @@ func Test_ORM_DeleteProposal(t *testing.T) { }, { name: "cancelled proposal", - before: func(orm *TestORM) int64 { + before: func(t *testing.T, orm *TestORM) int64 { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusCancelled, fmID) createJobSpec(t, orm, jpID) @@ -1141,7 +1166,7 @@ func Test_ORM_DeleteProposal(t *testing.T) { }, { name: "rejected proposal", - before: func(orm *TestORM) int64 { + before: func(t *testing.T, orm *TestORM) int64 { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusRejected, fmID) createJobSpec(t, orm, jpID) @@ -1153,7 +1178,7 @@ func Test_ORM_DeleteProposal(t *testing.T) { }, { name: "not found spec", - before: func(orm *TestORM) int64 { + before: func(t *testing.T, orm *TestORM) int64 { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusRejected, fmID) @@ -1163,7 +1188,7 @@ func Test_ORM_DeleteProposal(t *testing.T) { }, { name: "not found proposal", - before: func(orm *TestORM) int64 { + before: func(t *testing.T, orm *TestORM) int64 { return 0 }, wantErr: "sql: no rows in result set", @@ -1174,18 +1199,19 @@ func Test_ORM_DeleteProposal(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { + ctx := testutils.Context(t) orm := setupORM(t) - jpID := tc.before(orm) + jpID := tc.before(t, orm) - err := orm.DeleteProposal(jpID) + err := orm.DeleteProposal(ctx, jpID) if tc.wantErr != "" { require.EqualError(t, err, tc.wantErr) } else { require.NoError(t, err) - actual, err := orm.GetJobProposal(jpID) + actual, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, jpID, actual.ID) @@ -1201,7 +1227,7 @@ func Test_ORM_RevokeSpec(t *testing.T) { testCases := []struct { name string - before func(orm *TestORM) (int64, int64) + before func(t *testing.T, orm *TestORM) (int64, int64) wantProposalStatus feeds.JobProposalStatus wantSpecStatus feeds.SpecStatus wantErr string @@ -1209,7 +1235,7 @@ func Test_ORM_RevokeSpec(t *testing.T) { }{ { name: "pending proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) specID := createJobSpec(t, orm, jpID) @@ -1222,7 +1248,8 @@ func Test_ORM_RevokeSpec(t *testing.T) { }, { name: "approved proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) specID := createJobSpec(t, orm, jpID) @@ -1230,11 +1257,11 @@ func Test_ORM_RevokeSpec(t *testing.T) { externalJobID := uuid.NullUUID{UUID: uuid.New(), Valid: true} // Defer the FK requirement of an existing job for a job proposal. - require.NoError(t, utils.JustError(orm.db.Exec( + require.NoError(t, utils.JustError(orm.db.ExecContext(ctx, `SET CONSTRAINTS job_proposals_job_id_fkey DEFERRED`, ))) - err := orm.ApproveSpec(specID, externalJobID.UUID) + err := orm.ApproveSpec(ctx, specID, externalJobID.UUID) require.NoError(t, err) return jpID, specID @@ -1244,7 +1271,7 @@ func Test_ORM_RevokeSpec(t *testing.T) { }, { name: "cancelled proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusCancelled, fmID) specID := createJobSpec(t, orm, jpID) @@ -1256,7 +1283,7 @@ func Test_ORM_RevokeSpec(t *testing.T) { }, { name: "rejected proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusRejected, fmID) specID := createJobSpec(t, orm, jpID) @@ -1268,7 +1295,7 @@ func Test_ORM_RevokeSpec(t *testing.T) { }, { name: "deleted proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusDeleted, fmID) specID := createJobSpec(t, orm, jpID) @@ -1280,7 +1307,7 @@ func Test_ORM_RevokeSpec(t *testing.T) { }, { name: "not found", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { return 0, 0 }, wantErr: "sql: no rows in result set", @@ -1291,18 +1318,19 @@ func Test_ORM_RevokeSpec(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { + ctx := testutils.Context(t) orm := setupORM(t) - jpID, specID := tc.before(orm) + jpID, specID := tc.before(t, orm) - err := orm.RevokeSpec(specID) + err := orm.RevokeSpec(ctx, specID) if tc.wantErr != "" { require.EqualError(t, err, tc.wantErr) } else { require.NoError(t, err) - actualJP, err := orm.GetJobProposal(jpID) + actualJP, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, tc.wantProposalStatus, actualJP.Status) @@ -1318,6 +1346,7 @@ func Test_ORM_RevokeSpec(t *testing.T) { func Test_ORM_ExistsSpecByJobProposalIDAndVersion(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -1327,17 +1356,18 @@ func Test_ORM_ExistsSpecByJobProposalIDAndVersion(t *testing.T) { createJobSpec(t, orm, jpID) - exists, err := orm.ExistsSpecByJobProposalIDAndVersion(jpID, 1) + exists, err := orm.ExistsSpecByJobProposalIDAndVersion(ctx, jpID, 1) require.NoError(t, err) require.True(t, exists) - exists, err = orm.ExistsSpecByJobProposalIDAndVersion(jpID, 2) + exists, err = orm.ExistsSpecByJobProposalIDAndVersion(ctx, jpID, 2) require.NoError(t, err) require.False(t, exists) } func Test_ORM_GetSpec(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -1346,7 +1376,7 @@ func Test_ORM_GetSpec(t *testing.T) { specID = createJobSpec(t, orm, jpID) ) - actual, err := orm.GetSpec(specID) + actual, err := orm.GetSpec(ctx, specID) require.NoError(t, err) assert.Equal(t, "spec data", actual.Definition) @@ -1357,6 +1387,7 @@ func Test_ORM_GetSpec(t *testing.T) { func Test_ORM_GetApprovedSpec(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -1368,23 +1399,23 @@ func Test_ORM_GetApprovedSpec(t *testing.T) { // Defer the FK requirement of a job proposal so we don't have to setup a // real job. - require.NoError(t, utils.JustError(orm.db.Exec( + require.NoError(t, utils.JustError(orm.db.ExecContext(ctx, `SET CONSTRAINTS job_proposals_job_id_fkey DEFERRED`, ))) - err := orm.ApproveSpec(specID, externalJobID.UUID) + err := orm.ApproveSpec(ctx, specID, externalJobID.UUID) require.NoError(t, err) - actual, err := orm.GetApprovedSpec(jpID) + actual, err := orm.GetApprovedSpec(ctx, jpID) require.NoError(t, err) assert.Equal(t, specID, actual.ID) assert.Equal(t, feeds.SpecStatusApproved, actual.Status) - err = orm.CancelSpec(specID) + err = orm.CancelSpec(ctx, specID) require.NoError(t, err) - _, err = orm.GetApprovedSpec(jpID) + _, err = orm.GetApprovedSpec(ctx, jpID) require.Error(t, err) assert.ErrorIs(t, err, sql.ErrNoRows) @@ -1392,6 +1423,7 @@ func Test_ORM_GetApprovedSpec(t *testing.T) { func Test_ORM_GetLatestSpec(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -1400,7 +1432,7 @@ func Test_ORM_GetLatestSpec(t *testing.T) { ) _ = createJobSpec(t, orm, jpID) - spec2ID, err := orm.CreateSpec(feeds.JobProposalSpec{ + spec2ID, err := orm.CreateSpec(ctx, feeds.JobProposalSpec{ Definition: "spec data", Version: 2, Status: feeds.SpecStatusPending, @@ -1408,7 +1440,7 @@ func Test_ORM_GetLatestSpec(t *testing.T) { }) require.NoError(t, err) - actual, err := orm.GetSpec(spec2ID) + actual, err := orm.GetSpec(ctx, spec2ID) require.NoError(t, err) assert.Equal(t, spec2ID, actual.ID) @@ -1420,6 +1452,7 @@ func Test_ORM_GetLatestSpec(t *testing.T) { func Test_ORM_ListSpecsByJobProposalIDs(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -1433,7 +1466,7 @@ func Test_ORM_ListSpecsByJobProposalIDs(t *testing.T) { createJobSpec(t, orm, jp1ID) createJobSpec(t, orm, jp2ID) - specs, err := orm.ListSpecsByJobProposalIDs([]int64{jp1ID, jp2ID}) + specs, err := orm.ListSpecsByJobProposalIDs(ctx, []int64{jp1ID, jp2ID}) require.NoError(t, err) require.Len(t, specs, 2) @@ -1457,14 +1490,14 @@ func Test_ORM_RejectSpec(t *testing.T) { testCases := []struct { name string - before func(orm *TestORM) (int64, int64) + before func(t *testing.T, orm *TestORM) (int64, int64) wantSpecStatus feeds.SpecStatus wantProposalStatus feeds.JobProposalStatus wantErr string }{ { name: "pending proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) specID := createJobSpec(t, orm, jpID) @@ -1476,7 +1509,8 @@ func Test_ORM_RejectSpec(t *testing.T) { }, { name: "approved proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { + ctx := testutils.Context(t) fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusPending, fmID) specID := createJobSpec(t, orm, jpID) @@ -1484,11 +1518,11 @@ func Test_ORM_RejectSpec(t *testing.T) { externalJobID := uuid.NullUUID{UUID: uuid.New(), Valid: true} // Defer the FK requirement of an existing job for a job proposal. - require.NoError(t, utils.JustError(orm.db.Exec( + require.NoError(t, utils.JustError(orm.db.ExecContext(ctx, `SET CONSTRAINTS job_proposals_job_id_fkey DEFERRED`, ))) - err := orm.ApproveSpec(specID, externalJobID.UUID) + err := orm.ApproveSpec(ctx, specID, externalJobID.UUID) require.NoError(t, err) return jpID, specID @@ -1498,7 +1532,7 @@ func Test_ORM_RejectSpec(t *testing.T) { }, { name: "cancelled proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusCancelled, fmID) specID := createJobSpec(t, orm, jpID) @@ -1510,7 +1544,7 @@ func Test_ORM_RejectSpec(t *testing.T) { }, { name: "deleted proposal", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { fmID := createFeedsManager(t, orm) jpID := createJobProposal(t, orm, feeds.JobProposalStatusDeleted, fmID) specID := createJobSpec(t, orm, jpID) @@ -1522,7 +1556,7 @@ func Test_ORM_RejectSpec(t *testing.T) { }, { name: "not found", - before: func(orm *TestORM) (int64, int64) { + before: func(t *testing.T, orm *TestORM) (int64, int64) { return 0, 0 }, wantErr: "sql: no rows in result set", @@ -1533,24 +1567,25 @@ func Test_ORM_RejectSpec(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { + ctx := testutils.Context(t) orm := setupORM(t) - jpID, specID := tc.before(orm) + jpID, specID := tc.before(t, orm) - err := orm.RejectSpec(specID) + err := orm.RejectSpec(ctx, specID) if tc.wantErr != "" { require.EqualError(t, err, tc.wantErr) } else { require.NoError(t, err) - actual, err := orm.GetSpec(specID) + actual, err := orm.GetSpec(ctx, specID) require.NoError(t, err) assert.Equal(t, specID, actual.ID) assert.Equal(t, tc.wantSpecStatus, actual.Status) - actualJP, err := orm.GetJobProposal(jpID) + actualJP, err := orm.GetJobProposal(ctx, jpID) require.NoError(t, err) assert.Equal(t, tc.wantProposalStatus, actualJP.Status) @@ -1562,6 +1597,7 @@ func Test_ORM_RejectSpec(t *testing.T) { func Test_ORM_UpdateSpecDefinition(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -1570,13 +1606,13 @@ func Test_ORM_UpdateSpecDefinition(t *testing.T) { specID = createJobSpec(t, orm, jpID) ) - prev, err := orm.GetSpec(specID) + prev, err := orm.GetSpec(ctx, specID) require.NoError(t, err) - err = orm.UpdateSpecDefinition(specID, "updated spec") + err = orm.UpdateSpecDefinition(ctx, specID, "updated spec") require.NoError(t, err) - actual, err := orm.GetSpec(specID) + actual, err := orm.GetSpec(ctx, specID) require.NoError(t, err) assert.Equal(t, specID, actual.ID) @@ -1584,7 +1620,7 @@ func Test_ORM_UpdateSpecDefinition(t *testing.T) { require.Equal(t, "updated spec", actual.Definition) // Not found - err = orm.UpdateSpecDefinition(-1, "updated spec") + err = orm.UpdateSpecDefinition(ctx, -1, "updated spec") require.Error(t, err) } @@ -1592,6 +1628,7 @@ func Test_ORM_UpdateSpecDefinition(t *testing.T) { func Test_ORM_IsJobManaged(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( orm = setupORM(t) @@ -1603,14 +1640,14 @@ func Test_ORM_IsJobManaged(t *testing.T) { j := createJob(t, orm.db, externalJobID.UUID) - isManaged, err := orm.IsJobManaged(int64(j.ID)) + isManaged, err := orm.IsJobManaged(ctx, int64(j.ID)) require.NoError(t, err) assert.False(t, isManaged) - err = orm.ApproveSpec(specID, externalJobID.UUID) + err = orm.ApproveSpec(ctx, specID, externalJobID.UUID) require.NoError(t, err) - isManaged, err = orm.IsJobManaged(int64(j.ID)) + isManaged, err = orm.IsJobManaged(ctx, int64(j.ID)) require.NoError(t, err) assert.True(t, isManaged) } @@ -1640,7 +1677,8 @@ func createFeedsManager(t *testing.T, orm feeds.ORM) int64 { PublicKey: publicKey, } - id, err := orm.CreateManager(mgr) + ctx := testutils.Context(t) + id, err := orm.CreateManager(ctx, mgr) require.NoError(t, err) return id @@ -1658,7 +1696,7 @@ func createJob(t *testing.T, db *sqlx.DB, externalJobID uuid.UUID) *job.Job { bridgeORM = bridges.NewORM(db) relayExtenders = evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) ) - orm := job.NewORM(db, pipelineORM, bridgeORM, keyStore, lggr, config.Database()) + orm := job.NewORM(db, pipelineORM, bridgeORM, keyStore, lggr) require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) require.NoError(t, keyStore.P2P().Add(ctx, cltest.DefaultP2PKey)) @@ -1679,7 +1717,7 @@ func createJob(t *testing.T, db *sqlx.DB, externalJobID uuid.UUID) *job.Job { ) require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(ctx, &jb) require.NoError(t, err) return &jb @@ -1688,7 +1726,8 @@ func createJob(t *testing.T, db *sqlx.DB, externalJobID uuid.UUID) *job.Job { func createJobProposal(t *testing.T, orm feeds.ORM, status feeds.JobProposalStatus, fmID int64) int64 { t.Helper() - id, err := orm.CreateJobProposal(&feeds.JobProposal{ + ctx := testutils.Context(t) + id, err := orm.CreateJobProposal(ctx, &feeds.JobProposal{ RemoteUUID: uuid.New(), Status: status, FeedsManagerID: fmID, @@ -1702,7 +1741,8 @@ func createJobProposal(t *testing.T, orm feeds.ORM, status feeds.JobProposalStat func createJobSpec(t *testing.T, orm feeds.ORM, jpID int64) int64 { t.Helper() - id, err := orm.CreateSpec(feeds.JobProposalSpec{ + ctx := testutils.Context(t) + id, err := orm.CreateSpec(ctx, feeds.JobProposalSpec{ Definition: "spec data", Version: 1, Status: feeds.SpecStatusPending, diff --git a/core/services/feeds/service.go b/core/services/feeds/service.go index 8c4ea7a36bf..d6032befbdc 100644 --- a/core/services/feeds/service.go +++ b/core/services/feeds/service.go @@ -15,9 +15,8 @@ import ( "github.com/prometheus/client_golang/prometheus/promauto" "gopkg.in/guregu/null.v4" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/plugins" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -33,7 +32,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr" ocr2 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" ) @@ -66,17 +64,17 @@ type Service interface { Start(ctx context.Context) error Close() error - CountManagers() (int64, error) - GetManager(id int64) (*FeedsManager, error) - ListManagers() ([]FeedsManager, error) - ListManagersByIDs(ids []int64) ([]FeedsManager, error) + CountManagers(ctx context.Context) (int64, error) + GetManager(ctx context.Context, id int64) (*FeedsManager, error) + ListManagers(ctx context.Context) ([]FeedsManager, error) + ListManagersByIDs(ctx context.Context, ids []int64) ([]FeedsManager, error) RegisterManager(ctx context.Context, params RegisterManagerParams) (int64, error) UpdateManager(ctx context.Context, mgr FeedsManager) error CreateChainConfig(ctx context.Context, cfg ChainConfig) (int64, error) DeleteChainConfig(ctx context.Context, id int64) (int64, error) - GetChainConfig(id int64) (*ChainConfig, error) - ListChainConfigsByManagerIDs(mgrIDs []int64) ([]ChainConfig, error) + GetChainConfig(ctx context.Context, id int64) (*ChainConfig, error) + ListChainConfigsByManagerIDs(ctx context.Context, mgrIDs []int64) ([]ChainConfig, error) UpdateChainConfig(ctx context.Context, cfg ChainConfig) (int64, error) DeleteJob(ctx context.Context, args *DeleteJobArgs) (int64, error) @@ -85,19 +83,17 @@ type Service interface { RevokeJob(ctx context.Context, args *RevokeJobArgs) (int64, error) SyncNodeInfo(ctx context.Context, id int64) error - CountJobProposalsByStatus() (*JobProposalCounts, error) - GetJobProposal(id int64) (*JobProposal, error) - ListJobProposals() ([]JobProposal, error) - ListJobProposalsByManagersIDs(ids []int64) ([]JobProposal, error) + CountJobProposalsByStatus(ctx context.Context) (*JobProposalCounts, error) + GetJobProposal(ctx context.Context, id int64) (*JobProposal, error) + ListJobProposals(ctx context.Context) ([]JobProposal, error) + ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]JobProposal, error) ApproveSpec(ctx context.Context, id int64, force bool) error CancelSpec(ctx context.Context, id int64) error - GetSpec(id int64) (*JobProposalSpec, error) - ListSpecsByJobProposalIDs(ids []int64) ([]JobProposalSpec, error) + GetSpec(ctx context.Context, id int64) (*JobProposalSpec, error) + ListSpecsByJobProposalIDs(ctx context.Context, ids []int64) ([]JobProposalSpec, error) RejectSpec(ctx context.Context, id int64) error UpdateSpecDefinition(ctx context.Context, id int64, spec string) error - - Unsafe_SetConnectionsManager(ConnectionsManager) } type service struct { @@ -105,7 +101,7 @@ type service struct { orm ORM jobORM job.ORM - q pg.Q + ds sqlutil.DataSource csaKeyStore keystore.CSA p2pKeyStore keystore.P2P ocr1KeyStore keystore.OCR @@ -127,7 +123,7 @@ type service struct { func NewService( orm ORM, jobORM job.ORM, - db *sqlx.DB, + ds sqlutil.DataSource, jobSpawner job.Spawner, keyStore keystore.Master, gCfg GeneralConfig, @@ -135,7 +131,6 @@ func NewService( jobCfg JobConfig, ocrCfg OCRConfig, ocr2Cfg OCR2Config, - dbCfg pg.QConfig, legacyChains legacyevm.LegacyChainContainer, lggr logger.Logger, version string, @@ -145,7 +140,7 @@ func NewService( svc := &service{ orm: orm, jobORM: jobORM, - q: pg.NewQ(db, lggr, dbCfg), + ds: ds, jobSpawner: jobSpawner, p2pKeyStore: keyStore.P2P(), csaKeyStore: keyStore.CSA(), @@ -178,7 +173,7 @@ type RegisterManagerParams struct { // // Only a single feeds manager is currently supported. func (s *service) RegisterManager(ctx context.Context, params RegisterManagerParams) (int64, error) { - count, err := s.CountManagers() + count, err := s.CountManagers(ctx) if err != nil { return 0, err } @@ -193,16 +188,16 @@ func (s *service) RegisterManager(ctx context.Context, params RegisterManagerPar } var id int64 - q := s.q.WithOpts(pg.WithParentCtx(ctx)) - err = q.Transaction(func(tx pg.Queryer) error { + + err = s.orm.Transact(ctx, func(tx ORM) error { var txerr error - id, txerr = s.orm.CreateManager(&mgr, pg.WithQueryer(tx)) + id, txerr = tx.CreateManager(ctx, &mgr) if err != nil { return txerr } - if _, txerr = s.orm.CreateBatchChainConfig(params.ChainConfigs, pg.WithQueryer(tx)); txerr != nil { + if _, txerr = tx.CreateBatchChainConfig(ctx, params.ChainConfigs); txerr != nil { return txerr } @@ -229,7 +224,7 @@ func (s *service) SyncNodeInfo(ctx context.Context, id int64) error { return errors.Wrap(err, "could not fetch client") } - cfgs, err := s.orm.ListChainConfigsByManagerIDs([]int64{id}) + cfgs, err := s.orm.ListChainConfigsByManagerIDs(ctx, []int64{id}) if err != nil { return errors.Wrap(err, "could not fetch chain configs") } @@ -259,17 +254,9 @@ func (s *service) SyncNodeInfo(ctx context.Context, id int64) error { // UpdateManager updates the feed manager details, takes down the // connection and reestablishes a new connection with the updated public key. func (s *service) UpdateManager(ctx context.Context, mgr FeedsManager) error { - q := s.q.WithOpts(pg.WithParentCtx(ctx)) - err := q.Transaction(func(tx pg.Queryer) error { - txerr := s.orm.UpdateManager(mgr, pg.WithQueryer(tx)) - if txerr != nil { - return errors.Wrap(txerr, "could not update manager") - } - - return nil - }) + err := s.orm.UpdateManager(ctx, mgr) if err != nil { - return err + return errors.Wrap(err, "could not update manager") } if err := s.restartConnection(ctx, mgr); err != nil { @@ -280,8 +267,8 @@ func (s *service) UpdateManager(ctx context.Context, mgr FeedsManager) error { } // ListManagerServices lists all the manager services. -func (s *service) ListManagers() ([]FeedsManager, error) { - managers, err := s.orm.ListManagers() +func (s *service) ListManagers(ctx context.Context) ([]FeedsManager, error) { + managers, err := s.orm.ListManagers(ctx) if err != nil { return nil, errors.Wrap(err, "failed to get a list of managers") } @@ -294,8 +281,8 @@ func (s *service) ListManagers() ([]FeedsManager, error) { } // GetManager gets a manager service by id. -func (s *service) GetManager(id int64) (*FeedsManager, error) { - manager, err := s.orm.GetManager(id) +func (s *service) GetManager(ctx context.Context, id int64) (*FeedsManager, error) { + manager, err := s.orm.GetManager(ctx, id) if err != nil { return nil, errors.Wrap(err, "failed to get manager by ID") } @@ -305,8 +292,8 @@ func (s *service) GetManager(id int64) (*FeedsManager, error) { } // ListManagersByIDs get managers services by ids. -func (s *service) ListManagersByIDs(ids []int64) ([]FeedsManager, error) { - managers, err := s.orm.ListManagersByIDs(ids) +func (s *service) ListManagersByIDs(ctx context.Context, ids []int64) ([]FeedsManager, error) { + managers, err := s.orm.ListManagersByIDs(ctx, ids) if err != nil { return nil, errors.Wrap(err, "failed to list managers by IDs") } @@ -319,8 +306,8 @@ func (s *service) ListManagersByIDs(ids []int64) ([]FeedsManager, error) { } // CountManagers gets the total number of manager services -func (s *service) CountManagers() (int64, error) { - return s.orm.CountManagers() +func (s *service) CountManagers(ctx context.Context) (int64, error) { + return s.orm.CountManagers(ctx) } // CreateChainConfig creates a chain config. @@ -333,12 +320,12 @@ func (s *service) CreateChainConfig(ctx context.Context, cfg ChainConfig) (int64 } } - id, err := s.orm.CreateChainConfig(cfg) + id, err := s.orm.CreateChainConfig(ctx, cfg) if err != nil { return 0, errors.Wrap(err, "CreateChainConfig failed") } - mgr, err := s.orm.GetManager(cfg.FeedsManagerID) + mgr, err := s.orm.GetManager(ctx, cfg.FeedsManagerID) if err != nil { return 0, errors.Wrap(err, "CreateChainConfig: failed to fetch manager") } @@ -352,17 +339,17 @@ func (s *service) CreateChainConfig(ctx context.Context, cfg ChainConfig) (int64 // DeleteChainConfig deletes the chain config by id. func (s *service) DeleteChainConfig(ctx context.Context, id int64) (int64, error) { - cfg, err := s.orm.GetChainConfig(id) + cfg, err := s.orm.GetChainConfig(ctx, id) if err != nil { return 0, errors.Wrap(err, "DeleteChainConfig failed: could not get chain config") } - _, err = s.orm.DeleteChainConfig(id) + _, err = s.orm.DeleteChainConfig(ctx, id) if err != nil { return 0, errors.Wrap(err, "DeleteChainConfig failed") } - mgr, err := s.orm.GetManager(cfg.FeedsManagerID) + mgr, err := s.orm.GetManager(ctx, cfg.FeedsManagerID) if err != nil { return 0, errors.Wrap(err, "DeleteChainConfig: failed to fetch manager") } @@ -374,8 +361,8 @@ func (s *service) DeleteChainConfig(ctx context.Context, id int64) (int64, error return id, nil } -func (s *service) GetChainConfig(id int64) (*ChainConfig, error) { - cfg, err := s.orm.GetChainConfig(id) +func (s *service) GetChainConfig(ctx context.Context, id int64) (*ChainConfig, error) { + cfg, err := s.orm.GetChainConfig(ctx, id) if err != nil { return nil, errors.Wrap(err, "GetChainConfig failed") } @@ -383,8 +370,8 @@ func (s *service) GetChainConfig(id int64) (*ChainConfig, error) { return cfg, nil } -func (s *service) ListChainConfigsByManagerIDs(mgrIDs []int64) ([]ChainConfig, error) { - cfgs, err := s.orm.ListChainConfigsByManagerIDs(mgrIDs) +func (s *service) ListChainConfigsByManagerIDs(ctx context.Context, mgrIDs []int64) ([]ChainConfig, error) { + cfgs, err := s.orm.ListChainConfigsByManagerIDs(ctx, mgrIDs) return cfgs, errors.Wrap(err, "ListChainConfigsByManagerIDs failed") } @@ -398,12 +385,12 @@ func (s *service) UpdateChainConfig(ctx context.Context, cfg ChainConfig) (int64 } } - id, err := s.orm.UpdateChainConfig(cfg) + id, err := s.orm.UpdateChainConfig(ctx, cfg) if err != nil { return 0, errors.Wrap(err, "UpdateChainConfig failed") } - ccfg, err := s.orm.GetChainConfig(cfg.ID) + ccfg, err := s.orm.GetChainConfig(ctx, cfg.ID) if err != nil { return 0, errors.Wrap(err, "UpdateChainConfig failed: could not get chain config") } @@ -419,13 +406,13 @@ func (s *service) UpdateChainConfig(ctx context.Context, cfg ChainConfig) (int64 // // When we support multiple feed managers, we will need to change this to filter // by feeds manager -func (s *service) ListJobProposals() ([]JobProposal, error) { - return s.orm.ListJobProposals() +func (s *service) ListJobProposals(ctx context.Context) ([]JobProposal, error) { + return s.orm.ListJobProposals(ctx) } // ListJobProposalsByManagersIDs gets job proposals by feeds managers IDs -func (s *service) ListJobProposalsByManagersIDs(ids []int64) ([]JobProposal, error) { - return s.orm.ListJobProposalsByManagersIDs(ids) +func (s *service) ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]JobProposal, error) { + return s.orm.ListJobProposalsByManagersIDs(ctx, ids) } // DeleteJobArgs are the arguments to provide to the DeleteJob method. @@ -437,7 +424,7 @@ type DeleteJobArgs struct { // DeleteJob deletes a job proposal if it exist. The feeds manager id check // ensures that only the intended feed manager can make this request. func (s *service) DeleteJob(ctx context.Context, args *DeleteJobArgs) (int64, error) { - proposal, err := s.orm.GetJobProposalByRemoteUUID(args.RemoteUUID) + proposal, err := s.orm.GetJobProposalByRemoteUUID(ctx, args.RemoteUUID) if err != nil { if !errors.Is(err, sql.ErrNoRows) { return 0, errors.Wrap(err, "GetJobProposalByRemoteUUID failed to check existence of job proposal") @@ -456,14 +443,13 @@ func (s *service) DeleteJob(ctx context.Context, args *DeleteJobArgs) (int64, er return 0, errors.New("cannot delete a job proposal belonging to another feeds manager") } - pctx := pg.WithParentCtx(ctx) - if err = s.orm.DeleteProposal(proposal.ID, pctx); err != nil { + if err = s.orm.DeleteProposal(ctx, proposal.ID); err != nil { s.lggr.Errorw("Failed to delete the proposal", "err", err) return 0, errors.Wrap(err, "DeleteProposal failed") } - if err = s.observeJobProposalCounts(); err != nil { + if err = s.observeJobProposalCounts(ctx); err != nil { logger.Errorw("Failed to push metrics for job proposal deletion", err) } @@ -479,7 +465,7 @@ type RevokeJobArgs struct { // RevokeJob revokes a pending job proposal if it exist. The feeds manager // id check ensures that only the intended feed manager can make this request. func (s *service) RevokeJob(ctx context.Context, args *RevokeJobArgs) (int64, error) { - proposal, err := s.orm.GetJobProposalByRemoteUUID(args.RemoteUUID) + proposal, err := s.orm.GetJobProposalByRemoteUUID(ctx, args.RemoteUUID) if err != nil { if !errors.Is(err, sql.ErrNoRows) { return 0, errors.Wrap(err, "GetJobProposalByRemoteUUID failed to check existence of job proposal") @@ -495,7 +481,7 @@ func (s *service) RevokeJob(ctx context.Context, args *RevokeJobArgs) (int64, er } // get the latest spec for the proposal - latest, err := s.orm.GetLatestSpec(proposal.ID) + latest, err := s.orm.GetLatestSpec(ctx, proposal.ID) if err != nil { return 0, errors.Wrap(err, "GetLatestSpec failed to get latest spec") } @@ -504,8 +490,7 @@ func (s *service) RevokeJob(ctx context.Context, args *RevokeJobArgs) (int64, er return 0, errors.New("only pending job specs can be revoked") } - pctx := pg.WithParentCtx(ctx) - if err = s.orm.RevokeSpec(latest.ID, pctx); err != nil { + if err = s.orm.RevokeSpec(ctx, latest.ID); err != nil { s.lggr.Errorw("Failed to revoke the proposal", "err", err) return 0, errors.Wrap(err, "RevokeSpec failed") @@ -516,7 +501,7 @@ func (s *service) RevokeJob(ctx context.Context, args *RevokeJobArgs) (int64, er "job_proposal_spec_id", latest.ID, ) - if err = s.observeJobProposalCounts(); err != nil { + if err = s.observeJobProposalCounts(ctx); err != nil { logger.Errorw("Failed to push metrics for revoke job", err) } @@ -545,7 +530,7 @@ func (s *service) ProposeJob(ctx context.Context, args *ProposeJobArgs) (int64, return 0, err } - existing, err := s.orm.GetJobProposalByRemoteUUID(args.RemoteUUID) + existing, err := s.orm.GetJobProposalByRemoteUUID(ctx, args.RemoteUUID) if err != nil { if !errors.Is(err, sql.ErrNoRows) { return 0, errors.Wrap(err, "failed to check existence of job proposal") @@ -562,7 +547,7 @@ func (s *service) ProposeJob(ctx context.Context, args *ProposeJobArgs) (int64, // Check the version being proposed has not been previously proposed. var exists bool - exists, err = s.orm.ExistsSpecByJobProposalIDAndVersion(existing.ID, args.Version) + exists, err = s.orm.ExistsSpecByJobProposalIDAndVersion(ctx, existing.ID, args.Version) if err != nil { return 0, errors.Wrap(err, "failed to check existence of spec") } @@ -577,32 +562,31 @@ func (s *service) ProposeJob(ctx context.Context, args *ProposeJobArgs) (int64, ) var id int64 - q := s.q.WithOpts(pg.WithParentCtx(ctx)) - err = q.Transaction(func(tx pg.Queryer) error { + err = s.orm.Transact(ctx, func(tx ORM) error { var txerr error // Parse the Job Spec TOML to extract the name name := extractName(args.Spec) // Upsert job proposal - id, txerr = s.orm.UpsertJobProposal(&JobProposal{ + id, txerr = tx.UpsertJobProposal(ctx, &JobProposal{ Name: name, RemoteUUID: args.RemoteUUID, Status: JobProposalStatusPending, FeedsManagerID: args.FeedsManagerID, Multiaddrs: args.Multiaddrs, - }, pg.WithQueryer(tx)) + }) if txerr != nil { return errors.Wrap(txerr, "failed to upsert job proposal") } // Create the spec version - _, txerr = s.orm.CreateSpec(JobProposalSpec{ + _, txerr = tx.CreateSpec(ctx, JobProposalSpec{ Definition: args.Spec, Status: SpecStatusPending, Version: args.Version, JobProposalID: id, - }, pg.WithQueryer(tx)) + }) if txerr != nil { return errors.Wrap(txerr, "failed to create spec") } @@ -616,7 +600,7 @@ func (s *service) ProposeJob(ctx context.Context, args *ProposeJobArgs) (int64, // Track the given job proposal request promJobProposalRequest.Inc() - if err = s.observeJobProposalCounts(); err != nil { + if err = s.observeJobProposalCounts(ctx); err != nil { logger.Errorw("Failed to push metrics for propose job", err) } @@ -624,20 +608,18 @@ func (s *service) ProposeJob(ctx context.Context, args *ProposeJobArgs) (int64, } // GetJobProposal gets a job proposal by id. -func (s *service) GetJobProposal(id int64) (*JobProposal, error) { - return s.orm.GetJobProposal(id) +func (s *service) GetJobProposal(ctx context.Context, id int64) (*JobProposal, error) { + return s.orm.GetJobProposal(ctx, id) } // CountJobProposalsByStatus returns the count of job proposals with a given status. -func (s *service) CountJobProposalsByStatus() (*JobProposalCounts, error) { - return s.orm.CountJobProposalsByStatus() +func (s *service) CountJobProposalsByStatus(ctx context.Context) (*JobProposalCounts, error) { + return s.orm.CountJobProposalsByStatus(ctx) } // RejectSpec rejects a spec. func (s *service) RejectSpec(ctx context.Context, id int64) error { - pctx := pg.WithParentCtx(ctx) - - spec, err := s.orm.GetSpec(id, pctx) + spec, err := s.orm.GetSpec(ctx, id) if err != nil { return errors.Wrap(err, "orm: job proposal spec") } @@ -647,7 +629,7 @@ func (s *service) RejectSpec(ctx context.Context, id int64) error { return errors.New("must be a pending job proposal spec") } - proposal, err := s.orm.GetJobProposal(spec.JobProposalID, pctx) + proposal, err := s.orm.GetJobProposal(ctx, spec.JobProposalID) if err != nil { return errors.Wrap(err, "orm: job proposal") } @@ -662,9 +644,8 @@ func (s *service) RejectSpec(ctx context.Context, id int64) error { "job_proposal_spec_id", id, ) - q := s.q.WithOpts(pctx) - err = q.Transaction(func(tx pg.Queryer) error { - if err = s.orm.RejectSpec(id, pg.WithQueryer(tx)); err != nil { + err = s.orm.Transact(ctx, func(tx ORM) error { + if err = tx.RejectSpec(ctx, id); err != nil { return err } @@ -681,7 +662,7 @@ func (s *service) RejectSpec(ctx context.Context, id int64) error { return errors.Wrap(err, "could not reject job proposal") } - if err = s.observeJobProposalCounts(); err != nil { + if err = s.observeJobProposalCounts(ctx); err != nil { logger.Errorw("Failed to push metrics for job rejection", err) } @@ -690,25 +671,23 @@ func (s *service) RejectSpec(ctx context.Context, id int64) error { // IsJobManaged determines is a job is managed by the Feeds Manager. func (s *service) IsJobManaged(ctx context.Context, jobID int64) (bool, error) { - return s.orm.IsJobManaged(jobID, pg.WithParentCtx(ctx)) + return s.orm.IsJobManaged(ctx, jobID) } // ApproveSpec approves a spec for a job proposal and creates a job with the // spec. func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { - pctx := pg.WithParentCtx(ctx) - - spec, err := s.orm.GetSpec(id, pctx) + spec, err := s.orm.GetSpec(ctx, id) if err != nil { return errors.Wrap(err, "orm: job proposal spec") } - proposal, err := s.orm.GetJobProposal(spec.JobProposalID, pctx) + proposal, err := s.orm.GetJobProposal(ctx, spec.JobProposalID) if err != nil { return errors.Wrap(err, "orm: job proposal") } - if err = s.isApprovable(proposal.Status, proposal.ID, spec.Status, spec.ID); err != nil { + if err = s.isApprovable(ctx, proposal.Status, proposal.ID, spec.Status, spec.ID); err != nil { return err } @@ -741,17 +720,14 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { return errors.Wrap(err, "failed to approve job spec due to bridge check") } - q := s.q.WithOpts(pctx) - err = q.Transaction(func(tx pg.Queryer) error { + err = s.transact(ctx, func(tx datasources) error { var ( txerr error existingJobID int32 - - pgOpts = pg.WithQueryer(tx) ) // Use the external job id to check if a job already exists - foundJob, txerr := s.jobORM.FindJobByExternalJobID(j.ExternalJobID, pgOpts) + foundJob, txerr := tx.jobORM.FindJobByExternalJobID(ctx, j.ExternalJobID) if txerr != nil { // Return an error if the repository errors. If there is a not found // error we want to continue with approving the job. @@ -768,7 +744,7 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { if existingJobID == 0 { switch j.Type { case job.OffchainReporting, job.FluxMonitor: - existingJobID, txerr = s.findExistingJobForOCRFlux(j, pgOpts) + existingJobID, txerr = findExistingJobForOCRFlux(ctx, j, tx.jobORM) if txerr != nil { // Return an error if the repository errors. If there is a not found // error we want to continue with approving the job. @@ -777,7 +753,7 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { } } case job.OffchainReporting2, job.Bootstrap: - existingJobID, txerr = s.findExistingJobForOCR2(j, pgOpts) + existingJobID, txerr = findExistingJobForOCR2(ctx, j, tx.jobORM) if txerr != nil { // Return an error if the repository errors. If there is a not found // error we want to continue with approving the job. @@ -798,7 +774,7 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { } // Check if the job is managed by FMS - approvedSpec, serr := s.orm.GetApprovedSpec(proposal.ID, pgOpts) + approvedSpec, serr := tx.orm.GetApprovedSpec(ctx, proposal.ID) if serr != nil { if !errors.Is(serr, sql.ErrNoRows) { logger.Errorw("Failed to get approved spec", "err", serr) @@ -811,7 +787,7 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { // If a spec is found, cancel the existing job spec if serr == nil { - if cerr := s.orm.CancelSpec(approvedSpec.ID, pgOpts); cerr != nil { + if cerr := tx.orm.CancelSpec(ctx, approvedSpec.ID); cerr != nil { logger.Errorw("Failed to delete the cancel the spec", "err", cerr) return cerr @@ -819,7 +795,7 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { } // Delete the job - if serr = s.jobSpawner.DeleteJob(existingJobID, pgOpts); serr != nil { + if serr = s.jobSpawner.DeleteJob(ctx, tx.ds, existingJobID); serr != nil { logger.Errorw("Failed to delete the job", "err", serr) return errors.Wrap(serr, "DeleteJob failed") @@ -827,14 +803,14 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { } // Create the job - if txerr = s.jobSpawner.CreateJob(j, pgOpts); txerr != nil { + if txerr = s.jobSpawner.CreateJob(ctx, tx.ds, j); txerr != nil { logger.Errorw("Failed to create job", "err", txerr) return txerr } // Approve the job proposal spec - if txerr = s.orm.ApproveSpec(id, j.ExternalJobID, pgOpts); txerr != nil { + if txerr = tx.orm.ApproveSpec(ctx, id, j.ExternalJobID); txerr != nil { logger.Errorw("Failed to approve spec", "err", txerr) return txerr @@ -856,18 +832,32 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { return errors.Wrap(err, "could not approve job proposal") } - if err = s.observeJobProposalCounts(); err != nil { + if err = s.observeJobProposalCounts(ctx); err != nil { logger.Errorw("Failed to push metrics for job approval", err) } return nil } +type datasources struct { + ds sqlutil.DataSource + orm ORM + jobORM job.ORM +} + +func (s *service) transact(ctx context.Context, fn func(datasources) error) error { + return sqlutil.Transact(ctx, func(tx sqlutil.DataSource) datasources { + return datasources{ + ds: tx, + orm: s.orm.WithDataSource(tx), + jobORM: s.jobORM.WithDataSource(tx), + } + }, s.ds, nil, fn) +} + // CancelSpec cancels a spec for a job proposal. func (s *service) CancelSpec(ctx context.Context, id int64) error { - pctx := pg.WithParentCtx(ctx) - - spec, err := s.orm.GetSpec(id, pctx) + spec, err := s.orm.GetSpec(ctx, id) if err != nil { return errors.Wrap(err, "orm: job proposal spec") } @@ -876,7 +866,7 @@ func (s *service) CancelSpec(ctx context.Context, id int64) error { return errors.New("must be an approved job proposal spec") } - jp, err := s.orm.GetJobProposal(spec.JobProposalID, pg.WithParentCtx(ctx)) + jp, err := s.orm.GetJobProposal(ctx, spec.JobProposalID) if err != nil { return errors.Wrap(err, "orm: job proposal") } @@ -891,20 +881,18 @@ func (s *service) CancelSpec(ctx context.Context, id int64) error { "job_proposal_spec_id", id, ) - q := s.q.WithOpts(pctx) - err = q.Transaction(func(tx pg.Queryer) error { + err = s.transact(ctx, func(tx datasources) error { var ( - txerr error - pgOpts = pg.WithQueryer(tx) + txerr error ) - if txerr = s.orm.CancelSpec(id, pgOpts); txerr != nil { + if txerr = tx.orm.CancelSpec(ctx, id); txerr != nil { return txerr } // Delete the job if jp.ExternalJobID.Valid { - j, txerr := s.jobORM.FindJobByExternalJobID(jp.ExternalJobID.UUID, pgOpts) + j, txerr := tx.jobORM.FindJobByExternalJobID(ctx, jp.ExternalJobID.UUID) if txerr != nil { // Return an error if the repository errors. If there is a not found error we want // to continue with cancelling the spec but we won't have to cancel any jobs. @@ -914,7 +902,7 @@ func (s *service) CancelSpec(ctx context.Context, id int64) error { } if txerr == nil { - if serr := s.jobSpawner.DeleteJob(j.ID, pgOpts); serr != nil { + if serr := s.jobSpawner.DeleteJob(ctx, tx.ds, j.ID); serr != nil { return errors.Wrap(serr, "DeleteJob failed") } } @@ -934,7 +922,7 @@ func (s *service) CancelSpec(ctx context.Context, id int64) error { return err } - if err = s.observeJobProposalCounts(); err != nil { + if err = s.observeJobProposalCounts(ctx); err != nil { logger.Errorw("Failed to push metrics for job cancellation", err) } @@ -942,20 +930,18 @@ func (s *service) CancelSpec(ctx context.Context, id int64) error { } // ListSpecsByJobProposalIDs gets the specs which belong to the job proposal ids. -func (s *service) ListSpecsByJobProposalIDs(ids []int64) ([]JobProposalSpec, error) { - return s.orm.ListSpecsByJobProposalIDs(ids) +func (s *service) ListSpecsByJobProposalIDs(ctx context.Context, ids []int64) ([]JobProposalSpec, error) { + return s.orm.ListSpecsByJobProposalIDs(ctx, ids) } // GetSpec gets the spec details by id. -func (s *service) GetSpec(id int64) (*JobProposalSpec, error) { - return s.orm.GetSpec(id) +func (s *service) GetSpec(ctx context.Context, id int64) (*JobProposalSpec, error) { + return s.orm.GetSpec(ctx, id) } // UpdateSpecDefinition updates the spec's TOML definition. func (s *service) UpdateSpecDefinition(ctx context.Context, id int64, defn string) error { - pctx := pg.WithParentCtx(ctx) - - spec, err := s.orm.GetSpec(id, pctx) + spec, err := s.orm.GetSpec(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return errors.Wrap(err, "job proposal spec does not exist") @@ -969,7 +955,7 @@ func (s *service) UpdateSpecDefinition(ctx context.Context, id int64, defn strin } // Update the spec definition - if err = s.orm.UpdateSpecDefinition(id, defn, pctx); err != nil { + if err = s.orm.UpdateSpecDefinition(ctx, id, defn); err != nil { return errors.Wrap(err, "could not update job proposal") } @@ -985,7 +971,7 @@ func (s *service) Start(ctx context.Context) error { } // We only support a single feeds manager right now - mgrs, err := s.ListManagers() + mgrs, err := s.ListManagers(ctx) if err != nil { return err } @@ -998,7 +984,7 @@ func (s *service) Start(ctx context.Context) error { mgr := mgrs[0] s.connectFeedManager(ctx, mgr, privkey) - if err = s.observeJobProposalCounts(); err != nil { + if err = s.observeJobProposalCounts(ctx); err != nil { s.lggr.Error("failed to observe job proposal count when starting service", err) } @@ -1052,8 +1038,8 @@ func (s *service) getCSAPrivateKey() (privkey []byte, err error) { // observeJobProposalCounts is a helper method that queries the repository for the count of // job proposals by status and then updates prometheus gauges. -func (s *service) observeJobProposalCounts() error { - counts, err := s.CountJobProposalsByStatus() +func (s *service) observeJobProposalCounts(ctx context.Context) error { + counts, err := s.CountJobProposalsByStatus(ctx) if err != nil { return errors.Wrap(err, "failed to fetch counts of job proposals") } @@ -1073,18 +1059,8 @@ func (s *service) observeJobProposalCounts() error { return nil } -// Unsafe_SetConnectionsManager sets the ConnectionsManager on the service. -// -// We need to be able to inject a mock for the client to facilitate integration -// tests. -// -// ONLY TO BE USED FOR TESTING. -func (s *service) Unsafe_SetConnectionsManager(connMgr ConnectionsManager) { - s.connMgr = connMgr -} - // findExistingJobForOCR2 looks for existing job for OCR2 -func (s *service) findExistingJobForOCR2(j *job.Job, qopts pg.QOpt) (int32, error) { +func findExistingJobForOCR2(ctx context.Context, j *job.Job, tx job.ORM) (int32, error) { var contractID string var feedID *common.Hash @@ -1103,11 +1079,11 @@ func (s *service) findExistingJobForOCR2(j *job.Job, qopts pg.QOpt) (int32, erro return 0, errors.Errorf("unsupported job type: %s", j.Type) } - return s.jobORM.FindOCR2JobIDByAddress(contractID, feedID, qopts) + return tx.FindOCR2JobIDByAddress(ctx, contractID, feedID) } // findExistingJobForOCRFlux looks for existing job for OCR or flux -func (s *service) findExistingJobForOCRFlux(j *job.Job, qopts pg.QOpt) (int32, error) { +func findExistingJobForOCRFlux(ctx context.Context, j *job.Job, tx job.ORM) (int32, error) { var address types.EIP55Address var evmChainID *big.Big @@ -1124,7 +1100,7 @@ func (s *service) findExistingJobForOCRFlux(j *job.Job, qopts pg.QOpt) (int32, e return 0, errors.Errorf("unsupported job type: %s", j.Type) } - return s.jobORM.FindJobIDByAddress(address, evmChainID, qopts) + return tx.FindJobIDByAddress(ctx, address, evmChainID) } // generateJob validates and generates a job from a spec. @@ -1354,7 +1330,7 @@ func extractName(defn string) null.String { // isApprovable returns nil if a spec can be approved based on the current // proposal and spec status, and if it can't be approved, the reason as an // error. -func (s *service) isApprovable(propStatus JobProposalStatus, proposalID int64, specStatus SpecStatus, specID int64) error { +func (s *service) isApprovable(ctx context.Context, propStatus JobProposalStatus, proposalID int64, specStatus SpecStatus, specID int64) error { if propStatus == JobProposalStatusDeleted { return errors.New("cannot approve spec for a deleted job proposal") } @@ -1372,7 +1348,7 @@ func (s *service) isApprovable(propStatus JobProposalStatus, proposalID int64, s return errors.New("cannot approve a revoked spec") case SpecStatusCancelled: // Allowed to approve a cancelled job if it is the latest job - latest, serr := s.orm.GetLatestSpec(proposalID) + latest, serr := s.orm.GetLatestSpec(ctx, proposalID) if serr != nil { return errors.Wrap(serr, "failed to get latest spec") } @@ -1405,46 +1381,46 @@ func (ns NullService) Close() error { return nil } func (ns NullService) ApproveSpec(ctx context.Context, id int64, force bool) error { return ErrFeedsManagerDisabled } -func (ns NullService) CountManagers() (int64, error) { return 0, nil } -func (ns NullService) CountJobProposalsByStatus() (*JobProposalCounts, error) { +func (ns NullService) CountManagers(ctx context.Context) (int64, error) { return 0, nil } +func (ns NullService) CountJobProposalsByStatus(ctx context.Context) (*JobProposalCounts, error) { return nil, ErrFeedsManagerDisabled } func (ns NullService) CancelSpec(ctx context.Context, id int64) error { return ErrFeedsManagerDisabled } -func (ns NullService) GetJobProposal(id int64) (*JobProposal, error) { +func (ns NullService) GetJobProposal(ctx context.Context, id int64) (*JobProposal, error) { return nil, ErrFeedsManagerDisabled } -func (ns NullService) ListSpecsByJobProposalIDs(ids []int64) ([]JobProposalSpec, error) { +func (ns NullService) ListSpecsByJobProposalIDs(ctx context.Context, ids []int64) ([]JobProposalSpec, error) { return nil, ErrFeedsManagerDisabled } -func (ns NullService) GetManager(id int64) (*FeedsManager, error) { +func (ns NullService) GetManager(ctx context.Context, id int64) (*FeedsManager, error) { return nil, ErrFeedsManagerDisabled } -func (ns NullService) ListManagersByIDs(ids []int64) ([]FeedsManager, error) { +func (ns NullService) ListManagersByIDs(ctx context.Context, ids []int64) ([]FeedsManager, error) { return nil, ErrFeedsManagerDisabled } -func (ns NullService) GetSpec(id int64) (*JobProposalSpec, error) { +func (ns NullService) GetSpec(ctx context.Context, id int64) (*JobProposalSpec, error) { return nil, ErrFeedsManagerDisabled } -func (ns NullService) ListManagers() ([]FeedsManager, error) { return nil, nil } +func (ns NullService) ListManagers(ctx context.Context) ([]FeedsManager, error) { return nil, nil } func (ns NullService) CreateChainConfig(ctx context.Context, cfg ChainConfig) (int64, error) { return 0, ErrFeedsManagerDisabled } -func (ns NullService) GetChainConfig(id int64) (*ChainConfig, error) { +func (ns NullService) GetChainConfig(ctx context.Context, id int64) (*ChainConfig, error) { return nil, ErrFeedsManagerDisabled } func (ns NullService) DeleteChainConfig(ctx context.Context, id int64) (int64, error) { return 0, ErrFeedsManagerDisabled } -func (ns NullService) ListChainConfigsByManagerIDs(mgrIDs []int64) ([]ChainConfig, error) { +func (ns NullService) ListChainConfigsByManagerIDs(ctx context.Context, mgrIDs []int64) ([]ChainConfig, error) { return nil, ErrFeedsManagerDisabled } func (ns NullService) UpdateChainConfig(ctx context.Context, cfg ChainConfig) (int64, error) { return 0, ErrFeedsManagerDisabled } -func (ns NullService) ListJobProposals() ([]JobProposal, error) { return nil, nil } -func (ns NullService) ListJobProposalsByManagersIDs(ids []int64) ([]JobProposal, error) { +func (ns NullService) ListJobProposals(ctx context.Context) ([]JobProposal, error) { return nil, nil } +func (ns NullService) ListJobProposalsByManagersIDs(ctx context.Context, ids []int64) ([]JobProposal, error) { return nil, ErrFeedsManagerDisabled } func (ns NullService) ProposeJob(ctx context.Context, args *ProposeJobArgs) (int64, error) { @@ -1472,6 +1448,5 @@ func (ns NullService) IsJobManaged(ctx context.Context, jobID int64) (bool, erro func (ns NullService) UpdateSpecDefinition(ctx context.Context, id int64, spec string) error { return ErrFeedsManagerDisabled } -func (ns NullService) Unsafe_SetConnectionsManager(_ ConnectionsManager) {} //revive:enable diff --git a/core/services/feeds/service_test.go b/core/services/feeds/service_test.go index f83a98986e2..af656618f78 100644 --- a/core/services/feeds/service_test.go +++ b/core/services/feeds/service_test.go @@ -186,7 +186,7 @@ func setupTestServiceCfg(t *testing.T, overrideCfg func(c *chainlink.Config, s * keyStore.On("P2P").Return(p2pKeystore) keyStore.On("OCR").Return(ocr1Keystore) keyStore.On("OCR2").Return(ocr2Keystore) - svc := feeds.NewService(orm, jobORM, db, spawner, keyStore, gcfg, gcfg.Insecure(), gcfg.JobPipeline(), gcfg.OCR(), gcfg.OCR2(), gcfg.Database(), legacyChains, lggr, "1.0.0", nil) + svc := feeds.NewService(orm, jobORM, db, spawner, keyStore, gcfg, gcfg.Insecure(), gcfg.JobPipeline(), gcfg.OCR(), gcfg.OCR2(), legacyChains, lggr, "1.0.0", nil) svc.SetConnectionsManager(connMgr) return &TestService{ @@ -233,14 +233,19 @@ func Test_Service_RegisterManager(t *testing.T) { svc := setupTestService(t) - svc.orm.On("CountManagers").Return(int64(0), nil) - svc.orm.On("CreateManager", &mgr, mock.Anything). + svc.orm.On("CountManagers", mock.Anything).Return(int64(0), nil) + svc.orm.On("CreateManager", mock.Anything, &mgr, mock.Anything). Return(id, nil) - svc.orm.On("CreateBatchChainConfig", params.ChainConfigs, mock.Anything). + svc.orm.On("CreateBatchChainConfig", mock.Anything, params.ChainConfigs, mock.Anything). Return([]int64{}, nil) svc.csaKeystore.On("GetAll").Return([]csakey.KeyV2{key}, nil) // ListManagers runs in a goroutine so it might be called. svc.orm.On("ListManagers", testutils.Context(t)).Return([]feeds.FeedsManager{mgr}, nil).Maybe() + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) svc.connMgr.On("Connect", mock.IsType(feeds.ConnectOpts{})) actual, err := svc.RegisterManager(testutils.Context(t), params) @@ -254,6 +259,7 @@ func Test_Service_RegisterManager(t *testing.T) { func Test_Service_ListManagers(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( mgr = feeds.FeedsManager{} @@ -261,10 +267,10 @@ func Test_Service_ListManagers(t *testing.T) { ) svc := setupTestService(t) - svc.orm.On("ListManagers").Return(mgrs, nil) + svc.orm.On("ListManagers", mock.Anything).Return(mgrs, nil) svc.connMgr.On("IsConnected", mgr.ID).Return(false) - actual, err := svc.ListManagers() + actual, err := svc.ListManagers(ctx) require.NoError(t, err) assert.Equal(t, mgrs, actual) @@ -272,6 +278,7 @@ func Test_Service_ListManagers(t *testing.T) { func Test_Service_GetManager(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( id = int64(1) @@ -279,11 +286,11 @@ func Test_Service_GetManager(t *testing.T) { ) svc := setupTestService(t) - svc.orm.On("GetManager", id). + svc.orm.On("GetManager", mock.Anything, id). Return(&mgr, nil) svc.connMgr.On("IsConnected", mgr.ID).Return(false) - actual, err := svc.GetManager(id) + actual, err := svc.GetManager(ctx, id) require.NoError(t, err) assert.Equal(t, actual, &mgr) @@ -298,7 +305,7 @@ func Test_Service_UpdateFeedsManager(t *testing.T) { svc := setupTestService(t) - svc.orm.On("UpdateManager", mgr, mock.Anything).Return(nil) + svc.orm.On("UpdateManager", mock.Anything, mgr, mock.Anything).Return(nil) svc.csaKeystore.On("GetAll").Return([]csakey.KeyV2{key}, nil) svc.connMgr.On("Disconnect", mgr.ID).Return(nil) svc.connMgr.On("Connect", mock.IsType(feeds.ConnectOpts{})).Return(nil) @@ -309,6 +316,7 @@ func Test_Service_UpdateFeedsManager(t *testing.T) { func Test_Service_ListManagersByIDs(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( mgr = feeds.FeedsManager{} @@ -316,11 +324,11 @@ func Test_Service_ListManagersByIDs(t *testing.T) { ) svc := setupTestService(t) - svc.orm.On("ListManagersByIDs", []int64{mgr.ID}). + svc.orm.On("ListManagersByIDs", mock.Anything, []int64{mgr.ID}). Return(mgrs, nil) svc.connMgr.On("IsConnected", mgr.ID).Return(false) - actual, err := svc.ListManagersByIDs([]int64{mgr.ID}) + actual, err := svc.ListManagersByIDs(ctx, []int64{mgr.ID}) require.NoError(t, err) assert.Equal(t, mgrs, actual) @@ -328,16 +336,17 @@ func Test_Service_ListManagersByIDs(t *testing.T) { func Test_Service_CountManagers(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( count = int64(1) ) svc := setupTestService(t) - svc.orm.On("CountManagers"). + svc.orm.On("CountManagers", mock.Anything). Return(count, nil) - actual, err := svc.CountManagers() + actual, err := svc.CountManagers(ctx) require.NoError(t, err) assert.Equal(t, count, actual) @@ -369,10 +378,10 @@ func Test_Service_CreateChainConfig(t *testing.T) { svc = setupTestService(t) ) - svc.orm.On("CreateChainConfig", cfg).Return(int64(1), nil) - svc.orm.On("GetManager", mgr.ID).Return(&mgr, nil) + svc.orm.On("CreateChainConfig", mock.Anything, cfg).Return(int64(1), nil) + svc.orm.On("GetManager", mock.Anything, mgr.ID).Return(&mgr, nil) svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) - svc.orm.On("ListChainConfigsByManagerIDs", []int64{mgr.ID}).Return([]feeds.ChainConfig{cfg}, nil) + svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return([]feeds.ChainConfig{cfg}, nil) svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ Version: nodeVersion.Version, ChainConfigs: []*proto.ChainConfig{ @@ -430,11 +439,11 @@ func Test_Service_DeleteChainConfig(t *testing.T) { svc = setupTestService(t) ) - svc.orm.On("GetChainConfig", cfg.ID).Return(&cfg, nil) - svc.orm.On("DeleteChainConfig", cfg.ID).Return(cfg.ID, nil) - svc.orm.On("GetManager", mgr.ID).Return(&mgr, nil) + svc.orm.On("GetChainConfig", mock.Anything, cfg.ID).Return(&cfg, nil) + svc.orm.On("DeleteChainConfig", mock.Anything, cfg.ID).Return(cfg.ID, nil) + svc.orm.On("GetManager", mock.Anything, mgr.ID).Return(&mgr, nil) svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) - svc.orm.On("ListChainConfigsByManagerIDs", []int64{mgr.ID}).Return([]feeds.ChainConfig{}, nil) + svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return([]feeds.ChainConfig{}, nil) svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ Version: nodeVersion.Version, ChainConfigs: []*proto.ChainConfig{}, @@ -446,6 +455,7 @@ func Test_Service_DeleteChainConfig(t *testing.T) { } func Test_Service_ListChainConfigsByManagerIDs(t *testing.T) { + ctx := testutils.Context(t) var ( mgr = feeds.FeedsManager{ID: 1} cfg = feeds.ChainConfig{ @@ -457,9 +467,9 @@ func Test_Service_ListChainConfigsByManagerIDs(t *testing.T) { svc = setupTestService(t) ) - svc.orm.On("ListChainConfigsByManagerIDs", ids).Return([]feeds.ChainConfig{cfg}, nil) + svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, ids).Return([]feeds.ChainConfig{cfg}, nil) - actual, err := svc.ListChainConfigsByManagerIDs(ids) + actual, err := svc.ListChainConfigsByManagerIDs(ctx, ids) require.NoError(t, err) assert.Equal(t, []feeds.ChainConfig{cfg}, actual) } @@ -484,10 +494,10 @@ func Test_Service_UpdateChainConfig(t *testing.T) { svc = setupTestService(t) ) - svc.orm.On("UpdateChainConfig", cfg).Return(int64(1), nil) - svc.orm.On("GetChainConfig", cfg.ID).Return(&cfg, nil) + svc.orm.On("UpdateChainConfig", mock.Anything, cfg).Return(int64(1), nil) + svc.orm.On("GetChainConfig", mock.Anything, cfg.ID).Return(&cfg, nil) svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) - svc.orm.On("ListChainConfigsByManagerIDs", []int64{mgr.ID}).Return([]feeds.ChainConfig{cfg}, nil) + svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return([]feeds.ChainConfig{cfg}, nil) svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ Version: nodeVersion.Version, ChainConfigs: []*proto.ChainConfig{ @@ -640,10 +650,15 @@ func Test_Service_ProposeJob(t *testing.T) { { name: "Create success (Flux Monitor)", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", jpFluxMonitor.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) - svc.orm.On("UpsertJobProposal", &jpFluxMonitor, mock.Anything).Return(idFluxMonitor, nil) - svc.orm.On("CreateSpec", specFluxMonitor, mock.Anything).Return(int64(100), nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, jpFluxMonitor.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) + svc.orm.On("UpsertJobProposal", mock.Anything, &jpFluxMonitor).Return(idFluxMonitor, nil) + svc.orm.On("CreateSpec", mock.Anything, specFluxMonitor).Return(int64(100), nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, args: argsFluxMonitor, wantID: idFluxMonitor, @@ -651,10 +666,15 @@ func Test_Service_ProposeJob(t *testing.T) { { name: "Create success (OCR1)", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", jpOCR1.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) - svc.orm.On("UpsertJobProposal", &jpOCR1, mock.Anything).Return(idOCR1, nil) - svc.orm.On("CreateSpec", specOCR1, mock.Anything).Return(int64(100), nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, jpOCR1.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) + svc.orm.On("UpsertJobProposal", mock.Anything, &jpOCR1).Return(idOCR1, nil) + svc.orm.On("CreateSpec", mock.Anything, specOCR1).Return(int64(100), nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, args: argsOCR1, wantID: idOCR1, @@ -662,10 +682,15 @@ func Test_Service_ProposeJob(t *testing.T) { { name: "Create success (OCR2)", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", jpOCR2.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) - svc.orm.On("UpsertJobProposal", &jpOCR2, mock.Anything).Return(idOCR2, nil) - svc.orm.On("CreateSpec", specOCR2, mock.Anything).Return(int64(100), nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, jpOCR2.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) + svc.orm.On("UpsertJobProposal", mock.Anything, &jpOCR2).Return(idOCR2, nil) + svc.orm.On("CreateSpec", mock.Anything, specOCR2).Return(int64(100), nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, args: argsOCR2, wantID: idOCR2, @@ -673,10 +698,15 @@ func Test_Service_ProposeJob(t *testing.T) { { name: "Create success (Bootstrap)", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", jpBootstrap.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) - svc.orm.On("UpsertJobProposal", &jpBootstrap, mock.Anything).Return(idBootstrap, nil) - svc.orm.On("CreateSpec", specBootstrap, mock.Anything).Return(int64(102), nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, jpBootstrap.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) + svc.orm.On("UpsertJobProposal", mock.Anything, &jpBootstrap).Return(idBootstrap, nil) + svc.orm.On("CreateSpec", mock.Anything, specBootstrap).Return(int64(102), nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, args: argsBootstrap, wantID: idBootstrap, @@ -685,16 +715,21 @@ func Test_Service_ProposeJob(t *testing.T) { name: "Update success", before: func(svc *TestService) { svc.orm. - On("GetJobProposalByRemoteUUID", jpFluxMonitor.RemoteUUID). + On("GetJobProposalByRemoteUUID", mock.Anything, jpFluxMonitor.RemoteUUID). Return(&feeds.JobProposal{ FeedsManagerID: jpFluxMonitor.FeedsManagerID, RemoteUUID: jpFluxMonitor.RemoteUUID, Status: feeds.JobProposalStatusPending, }, nil) - svc.orm.On("ExistsSpecByJobProposalIDAndVersion", jpFluxMonitor.ID, argsFluxMonitor.Version).Return(false, nil) - svc.orm.On("UpsertJobProposal", &jpFluxMonitor, mock.Anything).Return(idFluxMonitor, nil) - svc.orm.On("CreateSpec", specFluxMonitor, mock.Anything).Return(int64(100), nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("ExistsSpecByJobProposalIDAndVersion", mock.Anything, jpFluxMonitor.ID, argsFluxMonitor.Version).Return(false, nil) + svc.orm.On("UpsertJobProposal", mock.Anything, &jpFluxMonitor).Return(idFluxMonitor, nil) + svc.orm.On("CreateSpec", mock.Anything, specFluxMonitor).Return(int64(100), nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, args: argsFluxMonitor, wantID: idFluxMonitor, @@ -717,7 +752,7 @@ func Test_Service_ProposeJob(t *testing.T) { name: "ensure an upsert validates the job proposal belongs to the feeds manager", before: func(svc *TestService) { svc.orm. - On("GetJobProposalByRemoteUUID", jpFluxMonitor.RemoteUUID). + On("GetJobProposalByRemoteUUID", mock.Anything, jpFluxMonitor.RemoteUUID). Return(&feeds.JobProposal{ FeedsManagerID: 2, RemoteUUID: jpFluxMonitor.RemoteUUID, @@ -730,13 +765,13 @@ func Test_Service_ProposeJob(t *testing.T) { name: "spec version already exists", before: func(svc *TestService) { svc.orm. - On("GetJobProposalByRemoteUUID", jpFluxMonitor.RemoteUUID). + On("GetJobProposalByRemoteUUID", mock.Anything, jpFluxMonitor.RemoteUUID). Return(&feeds.JobProposal{ FeedsManagerID: jpFluxMonitor.FeedsManagerID, RemoteUUID: jpFluxMonitor.RemoteUUID, Status: feeds.JobProposalStatusPending, }, nil) - svc.orm.On("ExistsSpecByJobProposalIDAndVersion", jpFluxMonitor.ID, argsFluxMonitor.Version).Return(true, nil) + svc.orm.On("ExistsSpecByJobProposalIDAndVersion", mock.Anything, jpFluxMonitor.ID, argsFluxMonitor.Version).Return(true, nil) }, args: argsFluxMonitor, wantErr: "proposed job spec version already exists", @@ -744,8 +779,13 @@ func Test_Service_ProposeJob(t *testing.T) { { name: "upsert error", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", jpFluxMonitor.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) - svc.orm.On("UpsertJobProposal", &jpFluxMonitor, mock.Anything).Return(int64(0), errors.New("orm error")) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, jpFluxMonitor.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) + svc.orm.On("UpsertJobProposal", mock.Anything, &jpFluxMonitor).Return(int64(0), errors.New("orm error")) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, args: argsFluxMonitor, wantErr: "failed to upsert job proposal", @@ -753,9 +793,14 @@ func Test_Service_ProposeJob(t *testing.T) { { name: "Create spec error", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", jpFluxMonitor.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) - svc.orm.On("UpsertJobProposal", &jpFluxMonitor, mock.Anything).Return(idFluxMonitor, nil) - svc.orm.On("CreateSpec", specFluxMonitor, mock.Anything).Return(int64(0), errors.New("orm error")) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, jpFluxMonitor.RemoteUUID).Return(new(feeds.JobProposal), sql.ErrNoRows) + svc.orm.On("UpsertJobProposal", mock.Anything, &jpFluxMonitor).Return(idFluxMonitor, nil) + svc.orm.On("CreateSpec", mock.Anything, specFluxMonitor).Return(int64(0), errors.New("orm error")) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, args: argsFluxMonitor, wantErr: "failed to create spec", @@ -820,9 +865,9 @@ func Test_Service_DeleteJob(t *testing.T) { { name: "Delete success", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", approved.RemoteUUID).Return(&approved, nil) - svc.orm.On("DeleteProposal", approved.ID, mock.Anything).Return(nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, approved.RemoteUUID).Return(&approved, nil) + svc.orm.On("DeleteProposal", mock.Anything, approved.ID).Return(nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) }, args: args, wantID: approved.ID, @@ -831,7 +876,7 @@ func Test_Service_DeleteJob(t *testing.T) { name: "Job proposal being deleted belongs to the feeds manager", before: func(svc *TestService) { svc.orm. - On("GetJobProposalByRemoteUUID", approved.RemoteUUID). + On("GetJobProposalByRemoteUUID", mock.Anything, approved.RemoteUUID). Return(&feeds.JobProposal{ FeedsManagerID: 2, RemoteUUID: approved.RemoteUUID, @@ -844,7 +889,7 @@ func Test_Service_DeleteJob(t *testing.T) { { name: "Get proposal error", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", approved.RemoteUUID).Return(nil, errors.New("orm error")) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, approved.RemoteUUID).Return(nil, errors.New("orm error")) }, args: args, wantErr: "GetJobProposalByRemoteUUID failed", @@ -852,7 +897,7 @@ func Test_Service_DeleteJob(t *testing.T) { { name: "No proposal error", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", approved.RemoteUUID).Return(nil, sql.ErrNoRows) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, approved.RemoteUUID).Return(nil, sql.ErrNoRows) }, args: args, wantErr: "GetJobProposalByRemoteUUID did not find any proposals to delete", @@ -860,8 +905,8 @@ func Test_Service_DeleteJob(t *testing.T) { { name: "Delete proposal error", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", approved.RemoteUUID).Return(&approved, nil) - svc.orm.On("DeleteProposal", approved.ID, mock.Anything).Return(errors.New("orm error")) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, approved.RemoteUUID).Return(&approved, nil) + svc.orm.On("DeleteProposal", mock.Anything, approved.ID).Return(errors.New("orm error")) }, args: args, wantErr: "DeleteProposal failed", @@ -960,10 +1005,10 @@ answer1 [type=median index=0]; { name: "Revoke success when latest spec status is pending", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(pendingProposal, nil) - svc.orm.On("GetLatestSpec", pendingSpec.JobProposalID).Return(pendingSpec, nil) - svc.orm.On("RevokeSpec", pendingSpec.ID, mock.Anything).Return(nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(pendingProposal, nil) + svc.orm.On("GetLatestSpec", mock.Anything, pendingSpec.JobProposalID).Return(pendingSpec, nil) + svc.orm.On("RevokeSpec", mock.Anything, pendingSpec.ID).Return(nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) }, args: args, wantID: pendingProposal.ID, @@ -971,16 +1016,16 @@ answer1 [type=median index=0]; { name: "Revoke success when latest spec status is cancelled", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(pendingProposal, nil) - svc.orm.On("GetLatestSpec", pendingSpec.JobProposalID).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(pendingProposal, nil) + svc.orm.On("GetLatestSpec", mock.Anything, pendingSpec.JobProposalID).Return(&feeds.JobProposalSpec{ ID: 20, Status: feeds.SpecStatusCancelled, JobProposalID: pendingProposal.ID, Version: 1, Definition: defn, }, nil) - svc.orm.On("RevokeSpec", pendingSpec.ID, mock.Anything).Return(nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("RevokeSpec", mock.Anything, pendingSpec.ID).Return(nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) }, args: args, wantID: pendingProposal.ID, @@ -989,7 +1034,7 @@ answer1 [type=median index=0]; name: "Job proposal being revoked belongs to the feeds manager", before: func(svc *TestService) { svc.orm. - On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID). + On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID). Return(&feeds.JobProposal{ FeedsManagerID: 2, RemoteUUID: pendingProposal.RemoteUUID, @@ -1002,7 +1047,7 @@ answer1 [type=median index=0]; { name: "Get proposal error", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(nil, errors.New("orm error")) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(nil, errors.New("orm error")) }, args: args, wantErr: "GetJobProposalByRemoteUUID failed", @@ -1010,7 +1055,7 @@ answer1 [type=median index=0]; { name: "No proposal error", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(nil, sql.ErrNoRows) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(nil, sql.ErrNoRows) }, args: args, wantErr: "GetJobProposalByRemoteUUID did not find any proposals to revoke", @@ -1018,8 +1063,8 @@ answer1 [type=median index=0]; { name: "Get latest spec error", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(pendingProposal, nil) - svc.orm.On("GetLatestSpec", pendingSpec.JobProposalID).Return(nil, sql.ErrNoRows) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(pendingProposal, nil) + svc.orm.On("GetLatestSpec", mock.Anything, pendingSpec.JobProposalID).Return(nil, sql.ErrNoRows) }, args: args, wantErr: "GetLatestSpec failed to get latest spec", @@ -1027,8 +1072,8 @@ answer1 [type=median index=0]; { name: "Not revokable due to spec status approved", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(pendingProposal, nil) - svc.orm.On("GetLatestSpec", pendingSpec.JobProposalID).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(pendingProposal, nil) + svc.orm.On("GetLatestSpec", mock.Anything, pendingSpec.JobProposalID).Return(&feeds.JobProposalSpec{ ID: 20, Status: feeds.SpecStatusApproved, JobProposalID: pendingProposal.ID, @@ -1042,8 +1087,8 @@ answer1 [type=median index=0]; { name: "Not revokable due to spec status rejected", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(pendingProposal, nil) - svc.orm.On("GetLatestSpec", pendingSpec.JobProposalID).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(pendingProposal, nil) + svc.orm.On("GetLatestSpec", mock.Anything, pendingSpec.JobProposalID).Return(&feeds.JobProposalSpec{ ID: 20, Status: feeds.SpecStatusRejected, JobProposalID: pendingProposal.ID, @@ -1057,8 +1102,8 @@ answer1 [type=median index=0]; { name: "Not revokable due to spec status already revoked", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(pendingProposal, nil) - svc.orm.On("GetLatestSpec", pendingSpec.JobProposalID).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(pendingProposal, nil) + svc.orm.On("GetLatestSpec", mock.Anything, pendingSpec.JobProposalID).Return(&feeds.JobProposalSpec{ ID: 20, Status: feeds.SpecStatusRevoked, JobProposalID: pendingProposal.ID, @@ -1072,13 +1117,13 @@ answer1 [type=median index=0]; { name: "Not revokable due to proposal status deleted", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(&feeds.JobProposal{ + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(&feeds.JobProposal{ ID: 1, FeedsManagerID: 1, RemoteUUID: remoteUUID, Status: feeds.JobProposalStatusDeleted, }, nil) - svc.orm.On("GetLatestSpec", pendingSpec.JobProposalID).Return(pendingSpec, nil) + svc.orm.On("GetLatestSpec", mock.Anything, pendingSpec.JobProposalID).Return(pendingSpec, nil) }, args: args, wantErr: "only pending job specs can be revoked", @@ -1086,9 +1131,9 @@ answer1 [type=median index=0]; { name: "Revoke proposal error", before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", pendingProposal.RemoteUUID).Return(pendingProposal, nil) - svc.orm.On("GetLatestSpec", pendingSpec.JobProposalID).Return(pendingSpec, nil) - svc.orm.On("RevokeSpec", pendingSpec.ID, mock.Anything).Return(errors.New("orm error")) + svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, pendingProposal.RemoteUUID).Return(pendingProposal, nil) + svc.orm.On("GetLatestSpec", mock.Anything, pendingSpec.JobProposalID).Return(pendingSpec, nil) + svc.orm.On("RevokeSpec", mock.Anything, pendingSpec.ID).Return(errors.New("orm error")) }, args: args, wantErr: "RevokeSpec failed", @@ -1168,7 +1213,7 @@ func Test_Service_SyncNodeInfo(t *testing.T) { svc := setupTestService(t) svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) - svc.orm.On("ListChainConfigsByManagerIDs", []int64{mgr.ID}).Return(chainConfigs, nil) + svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return(chainConfigs, nil) // OCR1 key fetching svc.p2pKeystore.On("Get", p2pKey.PeerID()).Return(p2pKey, nil) @@ -1227,7 +1272,7 @@ func Test_Service_IsJobManaged(t *testing.T) { ctx := testutils.Context(t) jobID := int64(1) - svc.orm.On("IsJobManaged", jobID, mock.Anything).Return(true, nil) + svc.orm.On("IsJobManaged", mock.Anything, jobID).Return(true, nil) isManaged, err := svc.IsJobManaged(ctx, jobID) require.NoError(t, err) @@ -1236,6 +1281,7 @@ func Test_Service_IsJobManaged(t *testing.T) { func Test_Service_ListJobProposals(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( jp = feeds.JobProposal{} @@ -1243,10 +1289,10 @@ func Test_Service_ListJobProposals(t *testing.T) { ) svc := setupTestService(t) - svc.orm.On("ListJobProposals"). + svc.orm.On("ListJobProposals", mock.Anything). Return(jps, nil) - actual, err := svc.ListJobProposals() + actual, err := svc.ListJobProposals(ctx) require.NoError(t, err) assert.Equal(t, actual, jps) @@ -1254,6 +1300,7 @@ func Test_Service_ListJobProposals(t *testing.T) { func Test_Service_ListJobProposalsByManagersIDs(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( jp = feeds.JobProposal{} @@ -1262,10 +1309,10 @@ func Test_Service_ListJobProposalsByManagersIDs(t *testing.T) { ) svc := setupTestService(t) - svc.orm.On("ListJobProposalsByManagersIDs", fmIDs). + svc.orm.On("ListJobProposalsByManagersIDs", mock.Anything, fmIDs). Return(jps, nil) - actual, err := svc.ListJobProposalsByManagersIDs(fmIDs) + actual, err := svc.ListJobProposalsByManagersIDs(ctx, fmIDs) require.NoError(t, err) assert.Equal(t, actual, jps) @@ -1273,6 +1320,7 @@ func Test_Service_ListJobProposalsByManagersIDs(t *testing.T) { func Test_Service_GetJobProposal(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( id = int64(1) @@ -1280,10 +1328,10 @@ func Test_Service_GetJobProposal(t *testing.T) { ) svc := setupTestService(t) - svc.orm.On("GetJobProposal", id). + svc.orm.On("GetJobProposal", mock.Anything, id). Return(&ms, nil) - actual, err := svc.GetJobProposal(id) + actual, err := svc.GetJobProposal(ctx, id) require.NoError(t, err) assert.Equal(t, actual, &ms) @@ -1320,12 +1368,12 @@ func Test_Service_CancelSpec(t *testing.T) { name: "success", before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.orm.On("CancelSpec", spec.ID, mock.Anything).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(j, nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.orm.On("CancelSpec", mock.Anything, spec.ID).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(j, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.fmsClient.On("CancelledJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -1334,7 +1382,9 @@ func Test_Service_CancelSpec(t *testing.T) { Version: int64(spec.Version), }, ).Return(&proto.CancelledJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, specID: spec.ID, }, @@ -1342,14 +1392,14 @@ func Test_Service_CancelSpec(t *testing.T) { name: "success without external job id", before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(&feeds.JobProposal{ + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(&feeds.JobProposal{ ID: 1, RemoteUUID: externalJobID, FeedsManagerID: 100, }, nil) - svc.orm.On("CancelSpec", spec.ID, mock.Anything).Return(nil) + svc.orm.On("CancelSpec", mock.Anything, spec.ID).Return(nil) svc.fmsClient.On("CancelledJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), &proto.CancelledJobRequest{ @@ -1357,7 +1407,9 @@ func Test_Service_CancelSpec(t *testing.T) { Version: int64(spec.Version), }, ).Return(&proto.CancelledJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, specID: spec.ID, }, @@ -1365,11 +1417,11 @@ func Test_Service_CancelSpec(t *testing.T) { name: "success without jobs", before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.orm.On("CancelSpec", spec.ID, mock.Anything).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) + svc.orm.On("CancelSpec", mock.Anything, spec.ID).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) svc.fmsClient.On("CancelledJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), &proto.CancelledJobRequest{ @@ -1377,14 +1429,16 @@ func Test_Service_CancelSpec(t *testing.T) { Version: int64(spec.Version), }, ).Return(&proto.CancelledJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, specID: spec.ID, }, { name: "spec does not exist", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(nil, errors.New("Not Found")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(nil, errors.New("Not Found")) }, specID: spec.ID, wantErr: "orm: job proposal spec: Not Found", @@ -1396,7 +1450,7 @@ func Test_Service_CancelSpec(t *testing.T) { ID: spec.ID, Status: feeds.SpecStatusPending, } - svc.orm.On("GetSpec", pspec.ID, mock.Anything).Return(pspec, nil) + svc.orm.On("GetSpec", mock.Anything, pspec.ID, mock.Anything).Return(pspec, nil) }, specID: spec.ID, wantErr: "must be an approved job proposal spec", @@ -1404,8 +1458,8 @@ func Test_Service_CancelSpec(t *testing.T) { { name: "job proposal does not exist", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(nil, errors.New("Not Found")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(nil, errors.New("Not Found")) }, specID: spec.ID, wantErr: "orm: job proposal: Not Found", @@ -1413,8 +1467,8 @@ func Test_Service_CancelSpec(t *testing.T) { { name: "rpc client not connected", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(nil, errors.New("Not Connected")) }, specID: spec.ID, @@ -1424,9 +1478,11 @@ func Test_Service_CancelSpec(t *testing.T) { name: "cancel spec orm fails", before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) - svc.orm.On("CancelSpec", spec.ID, mock.Anything).Return(errors.New("failure")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.orm.On("CancelSpec", mock.Anything, spec.ID).Return(errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, specID: spec.ID, wantErr: "failure", @@ -1435,11 +1491,13 @@ func Test_Service_CancelSpec(t *testing.T) { name: "find by external uuid orm fails", before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.orm.On("CancelSpec", spec.ID, mock.Anything).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, errors.New("failure")) + svc.orm.On("CancelSpec", mock.Anything, spec.ID).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, specID: spec.ID, wantErr: "FindJobByExternalJobID failed: failure", @@ -1448,12 +1506,14 @@ func Test_Service_CancelSpec(t *testing.T) { name: "delete job fails", before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.orm.On("CancelSpec", spec.ID, mock.Anything).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(j, nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(errors.New("failure")) + svc.orm.On("CancelSpec", mock.Anything, spec.ID).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(j, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, specID: spec.ID, wantErr: "DeleteJob failed: failure", @@ -1462,12 +1522,12 @@ func Test_Service_CancelSpec(t *testing.T) { name: "cancelled job rpc call fails", before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.orm.On("CancelSpec", spec.ID, mock.Anything).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(j, nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.orm.On("CancelSpec", mock.Anything, spec.ID).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(j, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.fmsClient.On("CancelledJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -1476,6 +1536,8 @@ func Test_Service_CancelSpec(t *testing.T) { Version: int64(spec.Version), }, ).Return(nil, errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, specID: spec.ID, wantErr: "failure", @@ -1509,6 +1571,7 @@ func Test_Service_CancelSpec(t *testing.T) { func Test_Service_GetSpec(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( id = int64(1) @@ -1516,10 +1579,10 @@ func Test_Service_GetSpec(t *testing.T) { ) svc := setupTestService(t) - svc.orm.On("GetSpec", id). + svc.orm.On("GetSpec", mock.Anything, id). Return(&spec, nil) - actual, err := svc.GetSpec(id) + actual, err := svc.GetSpec(ctx, id) require.NoError(t, err) assert.Equal(t, &spec, actual) @@ -1527,6 +1590,7 @@ func Test_Service_GetSpec(t *testing.T) { func Test_Service_ListSpecsByJobProposalIDs(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var ( id = int64(1) @@ -1536,10 +1600,10 @@ func Test_Service_ListSpecsByJobProposalIDs(t *testing.T) { ) svc := setupTestService(t) - svc.orm.On("ListSpecsByJobProposalIDs", []int64{jpID}). + svc.orm.On("ListSpecsByJobProposalIDs", mock.Anything, []int64{jpID}). Return(specs, nil) - actual, err := svc.ListSpecsByJobProposalIDs([]int64{jpID}) + actual, err := svc.ListSpecsByJobProposalIDs(ctx, []int64{jpID}) require.NoError(t, err) assert.Equal(t, specs, actual) @@ -1624,26 +1688,27 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(spec.ID, mock.Anything).Return(spec, nil) - svc.orm.EXPECT().GetJobProposal(jp.ID, mock.Anything).Return(jp, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, spec.ID).Return(spec, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, mock.IsType(uuid.UUID{}), - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -1652,7 +1717,9 @@ answer1 [type=median index=0]; Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -1662,27 +1729,28 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) - svc.orm.On("GetLatestSpec", cancelledSpec.JobProposalID).Return(cancelledSpec, nil) + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID).Return(cancelledSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.orm.On("GetLatestSpec", mock.Anything, cancelledSpec.JobProposalID).Return(cancelledSpec, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, cancelledSpec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -1691,7 +1759,9 @@ answer1 [type=median index=0]; Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: cancelledSpec.ID, force: false, @@ -1701,8 +1771,8 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(spec.ID, mock.Anything).Return(spec2, nil) - svc.orm.EXPECT().GetJobProposal(jp.ID, mock.Anything).Return(jp, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, spec.ID).Return(spec2, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, jp.ID).Return(jp, nil) }, id: spec.ID, force: false, @@ -1711,8 +1781,8 @@ answer1 [type=median index=0]; { name: "failed due to proposal being revoked", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(&feeds.JobProposal{ + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(&feeds.JobProposal{ ID: 1, Status: feeds.JobProposalStatusRevoked, }, nil) @@ -1724,8 +1794,8 @@ answer1 [type=median index=0]; { name: "failed due to proposal being deleted", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(&feeds.JobProposal{ + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(&feeds.JobProposal{ ID: jp.ID, Status: feeds.JobProposalStatusDeleted, }, nil) @@ -1742,8 +1812,8 @@ answer1 [type=median index=0]; Status: feeds.SpecStatusApproved, JobProposalID: jp.ID, } - svc.orm.On("GetSpec", aspec.ID, mock.Anything).Return(aspec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, aspec.ID, mock.Anything).Return(aspec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) }, id: spec.ID, force: false, @@ -1752,8 +1822,8 @@ answer1 [type=median index=0]; { name: "rejected spec fail", before: func(svc *TestService) { - svc.orm.On("GetSpec", cancelledSpec.ID, mock.Anything).Return(rejectedSpec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(rejectedSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) }, id: rejectedSpec.ID, force: false, @@ -1762,9 +1832,9 @@ answer1 [type=median index=0]; { name: "cancelled spec failed not latest spec", before: func(svc *TestService) { - svc.orm.On("GetSpec", cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) - svc.orm.On("GetLatestSpec", cancelledSpec.JobProposalID).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.orm.On("GetLatestSpec", mock.Anything, cancelledSpec.JobProposalID).Return(&feeds.JobProposalSpec{ ID: 21, Status: feeds.SpecStatusPending, JobProposalID: jp.ID, @@ -1781,11 +1851,13 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(j, nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(j, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -1796,12 +1868,14 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(j.ID, nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(j.ID, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -1812,27 +1886,28 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(spec.ID, mock.Anything).Return(spec, nil) - svc.orm.EXPECT().GetJobProposal(jp.ID, mock.Anything).Return(jp, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, spec.ID).Return(spec, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(j, nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(nil, sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(j, nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, sql.ErrNoRows) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -1841,7 +1916,9 @@ answer1 [type=median index=0]; Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -1851,28 +1928,29 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(spec.ID, mock.Anything).Return(spec, nil) - svc.orm.EXPECT().GetJobProposal(jp.ID, mock.Anything).Return(jp, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, spec.ID).Return(spec, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(j.ID, nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(nil, sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(j.ID, nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, sql.ErrNoRows) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -1881,7 +1959,9 @@ answer1 [type=median index=0]; Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -1891,29 +1971,30 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(spec.ID, mock.Anything).Return(spec, nil) - svc.orm.EXPECT().GetJobProposal(jp.ID, mock.Anything).Return(jp, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, spec.ID).Return(spec, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(j.ID, nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(&feeds.JobProposalSpec{ID: 100}, nil) - svc.orm.EXPECT().CancelSpec(int64(100), mock.Anything).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(j.ID, nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(&feeds.JobProposalSpec{ID: 100}, nil) + svc.orm.EXPECT().CancelSpec(mock.Anything, int64(100)).Return(nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -1922,7 +2003,9 @@ answer1 [type=median index=0]; Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -1930,7 +2013,7 @@ answer1 [type=median index=0]; { name: "spec does not exist", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(nil, errors.New("Not Found")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(nil, errors.New("Not Found")) }, id: spec.ID, force: false, @@ -1939,8 +2022,8 @@ answer1 [type=median index=0]; { name: "job proposal does not exist", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(nil, errors.New("Not Found")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(nil, errors.New("Not Found")) }, id: spec.ID, wantErr: "orm: job proposal: Not Found", @@ -1950,8 +2033,8 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(errors.New("bridges do not exist")) }, id: spec.ID, @@ -1960,8 +2043,8 @@ answer1 [type=median index=0]; { name: "rpc client not connected", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(nil, errors.New("Not Connected")) }, id: spec.ID, @@ -1973,11 +2056,13 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(spec.ID, mock.Anything).Return(spec, nil) - svc.orm.EXPECT().GetJobProposal(jp.ID, mock.Anything).Return(jp, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, spec.ID).Return(spec, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(j, nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(nil, errors.New("failure")) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(j, nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -1988,12 +2073,14 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(spec.ID, mock.Anything).Return(spec, nil) - svc.orm.EXPECT().GetJobProposal(jp.ID, mock.Anything).Return(jp, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, spec.ID).Return(spec, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(j.ID, nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(nil, errors.New("failure")) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(j.ID, nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -2004,12 +2091,14 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(spec.ID, mock.Anything).Return(spec, nil) - svc.orm.EXPECT().GetJobProposal(jp.ID, mock.Anything).Return(jp, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, spec.ID).Return(spec, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(j, nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(&feeds.JobProposalSpec{ID: 100}, nil) - svc.orm.EXPECT().CancelSpec(int64(100), mock.Anything).Return(errors.New("failure")) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(j, nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(&feeds.JobProposalSpec{ID: 100}, nil) + svc.orm.EXPECT().CancelSpec(mock.Anything, int64(100)).Return(errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -2020,13 +2109,15 @@ answer1 [type=median index=0]; httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.EXPECT().GetSpec(spec.ID, mock.Anything).Return(spec, nil) - svc.orm.EXPECT().GetJobProposal(jp.ID, mock.Anything).Return(jp, nil) + svc.orm.EXPECT().GetSpec(mock.Anything, spec.ID).Return(spec, nil) + svc.orm.EXPECT().GetJobProposal(mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(j.ID, nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(&feeds.JobProposalSpec{ID: 100}, nil) - svc.orm.EXPECT().CancelSpec(int64(100), mock.Anything).Return(errors.New("failure")) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(j.ID, nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(&feeds.JobProposalSpec{ID: 100}, nil) + svc.orm.EXPECT().CancelSpec(mock.Anything, int64(100)).Return(errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -2036,22 +2127,25 @@ answer1 [type=median index=0]; name: "create job error", httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). Return(errors.New("could not save")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2061,28 +2155,31 @@ answer1 [type=median index=0]; name: "approve spec orm error", httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2092,27 +2189,28 @@ answer1 [type=median index=0]; name: "fms call error", httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByAddress", address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindJobIDByAddress", mock.Anything, address, evmChainID, mock.Anything).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2121,6 +2219,8 @@ answer1 [type=median index=0]; Version: int64(spec.Version), }, ).Return(nil, errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2268,25 +2368,26 @@ updateInterval = "20m" httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2295,7 +2396,9 @@ updateInterval = "20m" Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2305,27 +2408,28 @@ updateInterval = "20m" httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) - svc.orm.On("GetLatestSpec", cancelledSpec.JobProposalID).Return(cancelledSpec, nil) + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.orm.On("GetLatestSpec", mock.Anything, cancelledSpec.JobProposalID).Return(cancelledSpec, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, cancelledSpec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2334,7 +2438,9 @@ updateInterval = "20m" Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: cancelledSpec.ID, force: false, @@ -2342,9 +2448,9 @@ updateInterval = "20m" { name: "cancelled spec failed not latest spec", before: func(svc *TestService) { - svc.orm.On("GetSpec", cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) - svc.orm.On("GetLatestSpec", cancelledSpec.JobProposalID).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.orm.On("GetLatestSpec", mock.Anything, cancelledSpec.JobProposalID).Return(&feeds.JobProposalSpec{ ID: 21, Status: feeds.SpecStatusPending, JobProposalID: jp.ID, @@ -2359,8 +2465,8 @@ updateInterval = "20m" { name: "rejected spec failed cannot be approved", before: func(svc *TestService) { - svc.orm.On("GetSpec", cancelledSpec.ID, mock.Anything).Return(rejectedSpec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(rejectedSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) }, id: rejectedSpec.ID, force: false, @@ -2371,11 +2477,13 @@ updateInterval = "20m" httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(j.ID, nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(j.ID, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2386,27 +2494,28 @@ updateInterval = "20m" httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(nil, sql.ErrNoRows) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(j.ID, nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(j.ID, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2415,7 +2524,9 @@ updateInterval = "20m" Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -2425,33 +2536,34 @@ updateInterval = "20m" httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(&feeds.JobProposalSpec{ ID: 20, Status: feeds.SpecStatusPending, JobProposalID: jp.ID, Version: 1, Definition: fmt.Sprintf(defn2, externalJobID.String(), &feedID), }, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(nil, sql.ErrNoRows) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, &feedID, mock.Anything).Return(j.ID, nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, &feedID).Return(j.ID, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2460,7 +2572,9 @@ updateInterval = "20m" Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -2470,28 +2584,29 @@ updateInterval = "20m" httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(&feeds.JobProposalSpec{ID: 100}, nil) - svc.orm.EXPECT().CancelSpec(int64(100), mock.Anything).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(j.ID, nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(&feeds.JobProposalSpec{ID: 100}, nil) + svc.orm.EXPECT().CancelSpec(mock.Anything, int64(100)).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(j.ID, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2500,7 +2615,9 @@ updateInterval = "20m" Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -2508,7 +2625,7 @@ updateInterval = "20m" { name: "spec does not exist", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(nil, errors.New("Not Found")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(nil, errors.New("Not Found")) }, id: spec.ID, force: false, @@ -2522,8 +2639,8 @@ updateInterval = "20m" JobProposalID: jp.ID, Status: feeds.SpecStatusApproved, } - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(aspec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(aspec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) }, id: spec.ID, force: false, @@ -2537,8 +2654,8 @@ updateInterval = "20m" JobProposalID: jp.ID, Status: feeds.SpecStatusRejected, } - svc.orm.On("GetSpec", rspec.ID, mock.Anything).Return(rspec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, rspec.ID, mock.Anything).Return(rspec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) }, id: spec.ID, force: false, @@ -2547,8 +2664,8 @@ updateInterval = "20m" { name: "job proposal does not exist", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(nil, errors.New("Not Found")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(nil, errors.New("Not Found")) }, id: spec.ID, wantErr: "orm: job proposal: Not Found", @@ -2558,8 +2675,8 @@ updateInterval = "20m" httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(errors.New("bridges do not exist")) }, id: spec.ID, @@ -2568,8 +2685,8 @@ updateInterval = "20m" { name: "rpc client not connected", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(nil, errors.New("Not Connected")) }, id: spec.ID, @@ -2580,22 +2697,25 @@ updateInterval = "20m" name: "create job error", httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). Return(errors.New("could not save")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2605,28 +2725,31 @@ updateInterval = "20m" name: "approve spec orm error", httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2636,27 +2759,28 @@ updateInterval = "20m" name: "fms call error", httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2665,6 +2789,8 @@ updateInterval = "20m" Version: int64(spec.Version), }, ).Return(nil, errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2774,25 +2900,26 @@ chainID = 0 httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2801,7 +2928,9 @@ chainID = 0 Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2811,27 +2940,28 @@ chainID = 0 httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) - svc.orm.On("GetLatestSpec", cancelledSpec.JobProposalID).Return(cancelledSpec, nil) + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.orm.On("GetLatestSpec", mock.Anything, cancelledSpec.JobProposalID).Return(cancelledSpec, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, cancelledSpec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2840,7 +2970,9 @@ chainID = 0 Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: cancelledSpec.ID, force: false, @@ -2848,9 +2980,9 @@ chainID = 0 { name: "cancelled spec failed not latest spec", before: func(svc *TestService) { - svc.orm.On("GetSpec", cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) - svc.orm.On("GetLatestSpec", cancelledSpec.JobProposalID).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) + svc.orm.On("GetLatestSpec", mock.Anything, cancelledSpec.JobProposalID).Return(&feeds.JobProposalSpec{ ID: 21, Status: feeds.SpecStatusPending, JobProposalID: jp.ID, @@ -2865,8 +2997,8 @@ chainID = 0 { name: "rejected spec failed cannot be approved", before: func(svc *TestService) { - svc.orm.On("GetSpec", cancelledSpec.ID, mock.Anything).Return(rejectedSpec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(rejectedSpec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) }, id: rejectedSpec.ID, force: false, @@ -2877,11 +3009,13 @@ chainID = 0 httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(j.ID, nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(j.ID, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -2892,27 +3026,28 @@ chainID = 0 httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(nil, sql.ErrNoRows) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(j.ID, nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(j.ID, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2921,7 +3056,9 @@ chainID = 0 Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -2931,33 +3068,34 @@ chainID = 0 httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(&feeds.JobProposalSpec{ ID: 20, Status: feeds.SpecStatusPending, JobProposalID: jp.ID, Version: 1, Definition: fmt.Sprintf(defn2, externalJobID.String(), feedID), }, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(nil, sql.ErrNoRows) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, &feedID, mock.Anything).Return(j.ID, nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, &feedID).Return(j.ID, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -2966,7 +3104,9 @@ chainID = 0 Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -2976,28 +3116,29 @@ chainID = 0 httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.orm.EXPECT().GetApprovedSpec(jp.ID, mock.Anything).Return(&feeds.JobProposalSpec{ID: 100}, nil) - svc.orm.EXPECT().CancelSpec(int64(100), mock.Anything).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(j.ID, nil) - svc.spawner.On("DeleteJob", j.ID, mock.Anything).Return(nil) + svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(&feeds.JobProposalSpec{ID: 100}, nil) + svc.orm.EXPECT().CancelSpec(mock.Anything, int64(100)).Return(nil) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(j.ID, nil) + svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -3006,7 +3147,9 @@ chainID = 0 Version: int64(spec.Version), }, ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: true, @@ -3014,7 +3157,7 @@ chainID = 0 { name: "spec does not exist", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(nil, errors.New("Not Found")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(nil, errors.New("Not Found")) }, id: spec.ID, force: false, @@ -3028,8 +3171,8 @@ chainID = 0 JobProposalID: jp.ID, Status: feeds.SpecStatusApproved, } - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(aspec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(aspec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) }, id: spec.ID, force: false, @@ -3043,8 +3186,8 @@ chainID = 0 JobProposalID: jp.ID, Status: feeds.SpecStatusRejected, } - svc.orm.On("GetSpec", rspec.ID, mock.Anything).Return(rspec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, rspec.ID).Return(rspec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) }, id: spec.ID, force: false, @@ -3053,8 +3196,8 @@ chainID = 0 { name: "job proposal does not exist", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(nil, errors.New("Not Found")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(nil, errors.New("Not Found")) }, id: spec.ID, wantErr: "orm: job proposal: Not Found", @@ -3064,8 +3207,8 @@ chainID = 0 httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(errors.New("bridges do not exist")) }, id: spec.ID, @@ -3074,8 +3217,8 @@ chainID = 0 { name: "rpc client not connected", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(nil, errors.New("Not Connected")) }, id: spec.ID, @@ -3086,22 +3229,25 @@ chainID = 0 name: "create job error", httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). Return(errors.New("could not save")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -3111,28 +3257,31 @@ chainID = 0 name: "approve spec orm error", httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -3142,27 +3291,28 @@ chainID = 0 name: "fms call error", httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", externalJobID, mock.Anything).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindOCR2JobIDByAddress", address, (*common.Hash)(nil), mock.Anything).Return(int32(0), sql.ErrNoRows) + svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) + svc.jobORM.On("FindOCR2JobIDByAddress", mock.Anything, address, (*common.Hash)(nil)).Return(int32(0), sql.ErrNoRows) svc.spawner. On("CreateJob", + mock.Anything, + mock.Anything, mock.MatchedBy(func(j *job.Job) bool { return j.Name.String == "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" }), - mock.Anything, ). - Run(func(args mock.Arguments) { (args.Get(0).(*job.Job)).ID = 1 }). + Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). Return(nil) svc.orm.On("ApproveSpec", + mock.Anything, spec.ID, externalJobID, - mock.Anything, ).Return(nil) svc.fmsClient.On("ApprovedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -3171,6 +3321,8 @@ chainID = 0 Version: int64(spec.Version), }, ).Return(nil, errors.New("failure")) + svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) + svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) }, id: spec.ID, force: false, @@ -3227,12 +3379,12 @@ func Test_Service_RejectSpec(t *testing.T) { { name: "Success", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.orm.On("RejectSpec", - spec.ID, mock.Anything, + spec.ID, ).Return(nil) svc.fmsClient.On("RejectedJob", mock.MatchedBy(func(ctx context.Context) bool { return true }), @@ -3241,20 +3393,25 @@ func Test_Service_RejectSpec(t *testing.T) { Version: int64(spec.Version), }, ).Return(&proto.RejectedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, }, { name: "Fails to get spec", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(nil, errors.New("failure")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(nil, errors.New("failure")) }, wantErr: "failure", }, { name: "Cannot be a rejected proposal", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(&feeds.JobProposalSpec{ + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(&feeds.JobProposalSpec{ Status: feeds.SpecStatusRejected, }, nil) }, @@ -3263,16 +3420,16 @@ func Test_Service_RejectSpec(t *testing.T) { { name: "Fails to get proposal", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(nil, errors.New("failure")) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(nil, errors.New("failure")) }, wantErr: "failure", }, { name: "FMS not connected", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(nil, errors.New("disconnected")) }, wantErr: "disconnected", @@ -3280,18 +3437,23 @@ func Test_Service_RejectSpec(t *testing.T) { { name: "Fails to update spec", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.orm.On("RejectSpec", mock.Anything, mock.Anything).Return(errors.New("failure")) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, wantErr: "failure", }, { name: "Fails to update spec", before: func(svc *TestService) { - svc.orm.On("GetSpec", spec.ID, mock.Anything).Return(spec, nil) - svc.orm.On("GetJobProposal", jp.ID, mock.Anything).Return(jp, nil) + svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) + svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) svc.orm.On("RejectSpec", mock.Anything, mock.Anything).Return(nil) svc.fmsClient. @@ -3302,6 +3464,11 @@ func Test_Service_RejectSpec(t *testing.T) { Version: int64(spec.Version), }). Return(nil, errors.New("rpc failure")) + transactCall := svc.orm.On("Transact", mock.Anything, mock.Anything) + transactCall.Run(func(args mock.Arguments) { + fn := args[1].(func(orm feeds.ORM) error) + transactCall.ReturnArguments = mock.Arguments{fn(svc.orm)} + }) }, wantErr: "rpc failure", }, @@ -3352,9 +3519,9 @@ func Test_Service_UpdateSpecDefinition(t *testing.T) { name: "success", before: func(svc *TestService) { svc.orm. - On("GetSpec", specID, mock.Anything). + On("GetSpec", mock.Anything, specID, mock.Anything). Return(spec, nil) - svc.orm.On("UpdateSpecDefinition", + svc.orm.On("UpdateSpecDefinition", mock.Anything, specID, updatedSpec, mock.Anything, @@ -3366,7 +3533,7 @@ func Test_Service_UpdateSpecDefinition(t *testing.T) { name: "does not exist", before: func(svc *TestService) { svc.orm. - On("GetSpec", specID, mock.Anything). + On("GetSpec", mock.Anything, specID, mock.Anything). Return(nil, sql.ErrNoRows) }, specID: specID, @@ -3376,7 +3543,7 @@ func Test_Service_UpdateSpecDefinition(t *testing.T) { name: "other get errors", before: func(svc *TestService) { svc.orm. - On("GetSpec", specID, mock.Anything). + On("GetSpec", mock.Anything, specID, mock.Anything). Return(nil, errors.New("other db error")) }, specID: specID, @@ -3391,7 +3558,7 @@ func Test_Service_UpdateSpecDefinition(t *testing.T) { } svc.orm. - On("GetSpec", specID, mock.Anything). + On("GetSpec", mock.Anything, specID, mock.Anything). Return(spec, nil) }, specID: specID, @@ -3443,18 +3610,18 @@ func Test_Service_StartStop(t *testing.T) { name: "success with a feeds manager connection", beforeFunc: func(svc *TestService) { svc.csaKeystore.On("GetAll").Return([]csakey.KeyV2{key}, nil) - svc.orm.On("ListManagers").Return([]feeds.FeedsManager{mgr}, nil) + svc.orm.On("ListManagers", mock.Anything).Return([]feeds.FeedsManager{mgr}, nil) svc.connMgr.On("IsConnected", mgr.ID).Return(false) svc.connMgr.On("Connect", mock.IsType(feeds.ConnectOpts{})) svc.connMgr.On("Close") - svc.orm.On("CountJobProposalsByStatus").Return(&feeds.JobProposalCounts{}, nil) + svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) }, }, { name: "success with no registered managers", beforeFunc: func(svc *TestService) { svc.csaKeystore.On("GetAll").Return([]csakey.KeyV2{key}, nil) - svc.orm.On("ListManagers").Return([]feeds.FeedsManager{}, nil) + svc.orm.On("ListManagers", mock.Anything).Return([]feeds.FeedsManager{}, nil) svc.connMgr.On("Close") }, }, diff --git a/core/services/fluxmonitorv2/delegate.go b/core/services/fluxmonitorv2/delegate.go index b7b0df77cc4..1f0b72877ff 100644 --- a/core/services/fluxmonitorv2/delegate.go +++ b/core/services/fluxmonitorv2/delegate.go @@ -5,8 +5,7 @@ import ( "github.com/pkg/errors" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" @@ -25,7 +24,7 @@ type DelegateConfig interface { // Delegate represents a Flux Monitor delegate type Delegate struct { cfg DelegateConfig - db *sqlx.DB + ds sqlutil.DataSource ethKeyStore keystore.Eth jobORM job.ORM pipelineORM pipeline.ORM @@ -43,13 +42,13 @@ func NewDelegate( jobORM job.ORM, pipelineORM pipeline.ORM, pipelineRunner pipeline.Runner, - db *sqlx.DB, + ds sqlutil.DataSource, legacyChains legacyevm.LegacyChainContainer, lggr logger.Logger, ) *Delegate { return &Delegate{ cfg: cfg, - db: db, + ds: ds, ethKeyStore: ethKeyStore, jobORM: jobORM, pipelineORM: pipelineORM, @@ -86,8 +85,8 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) (services [] fm, err := NewFromJobSpec( jb, - d.db, - NewORM(d.db, d.lggr, chain.TxManager(), strategy, checker), + d.ds, + NewORM(d.ds, d.lggr, chain.TxManager(), strategy, checker), d.jobORM, d.pipelineORM, NewKeyStore(d.ethKeyStore), diff --git a/core/services/fluxmonitorv2/flux_monitor.go b/core/services/fluxmonitorv2/flux_monitor.go index 5eebb319030..dd30156e15e 100644 --- a/core/services/fluxmonitorv2/flux_monitor.go +++ b/core/services/fluxmonitorv2/flux_monitor.go @@ -13,8 +13,6 @@ import ( "github.com/pkg/errors" "github.com/shopspring/decimal" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" @@ -149,7 +147,7 @@ func NewFluxMonitor( // validation. func NewFromJobSpec( jobSpec job.Job, - db *sqlx.DB, + ds sqlutil.DataSource, orm ORM, jobORM job.ORM, pipelineORM pipeline.ORM, @@ -250,7 +248,7 @@ func NewFromJobSpec( pipelineRunner, jobSpec, *jobSpec.PipelineSpec, - db, + ds, orm, jobORM, pipelineORM, @@ -760,7 +758,7 @@ func (fm *FluxMonitor) respondToNewRoundLog(log flux_aggregator_wrapper.FluxAggr result, err := results.FinalResult(newRoundLogger).SingularResult() if err != nil || result.Error != nil { newRoundLogger.Errorw("can't fetch answer", "err", err, "result", result) - fm.jobORM.TryRecordError(fm.spec.JobID, "Error polling") + fm.jobORM.TryRecordError(ctx, fm.spec.JobID, "Error polling") return } answer, err := utils.ToDecimal(result.Value) @@ -865,7 +863,7 @@ func (fm *FluxMonitor) pollIfEligible(pollReq PollRequestType, deviationChecker roundState, err := fm.roundState(0) if err != nil { l.Errorw("unable to determine eligibility to submit from FluxAggregator contract", "err", err) - fm.jobORM.TryRecordError(fm.spec.JobID, + fm.jobORM.TryRecordError(ctx, fm.spec.JobID, "Unable to call roundState method on provided contract. Check contract address.", ) @@ -885,7 +883,7 @@ func (fm *FluxMonitor) pollIfEligible(pollReq PollRequestType, deviationChecker roundStateNew, err2 := fm.roundState(roundState.RoundId) if err2 != nil { l.Errorw("unable to determine eligibility to submit from FluxAggregator contract", "err", err2) - fm.jobORM.TryRecordError(fm.spec.JobID, + fm.jobORM.TryRecordError(ctx, fm.spec.JobID, "Unable to call roundState method on provided contract. Check contract address.", ) @@ -962,13 +960,13 @@ func (fm *FluxMonitor) pollIfEligible(pollReq PollRequestType, deviationChecker run, results, err := fm.runner.ExecuteRun(ctx, fm.spec, vars, fm.logger) if err != nil { l.Errorw("can't fetch answer", "err", err) - fm.jobORM.TryRecordError(fm.spec.JobID, "Error polling") + fm.jobORM.TryRecordError(ctx, fm.spec.JobID, "Error polling") return } result, err := results.FinalResult(l).SingularResult() if err != nil || result.Error != nil { l.Errorw("can't fetch answer", "err", err, "result", result) - fm.jobORM.TryRecordError(fm.spec.JobID, "Error polling") + fm.jobORM.TryRecordError(ctx, fm.spec.JobID, "Error polling") return } answer, err := utils.ToDecimal(result.Value) @@ -1041,7 +1039,7 @@ func (fm *FluxMonitor) isValidSubmission(ctx context.Context, l logger.Logger, a "max", fm.submissionChecker.Max, "answer", answer, ) - fm.jobORM.TryRecordError(fm.spec.JobID, "Answer is outside acceptable range") + fm.jobORM.TryRecordError(ctx, fm.spec.JobID, "Answer is outside acceptable range") jobId := fm.spec.JobID jobName := fm.spec.JobName diff --git a/core/services/fluxmonitorv2/flux_monitor_test.go b/core/services/fluxmonitorv2/flux_monitor_test.go index 2ac424bceab..b3a5bcee6b9 100644 --- a/core/services/fluxmonitorv2/flux_monitor_test.go +++ b/core/services/fluxmonitorv2/flux_monitor_test.go @@ -515,6 +515,7 @@ func TestFluxMonitor_PollIfEligible_Creates_JobErr(t *testing.T) { tm.jobORM. On("TryRecordError", + mock.Anything, pipelineSpec.JobID, "Unable to call roundState method on provided contract. Check contract address.", ).Once() diff --git a/core/services/fluxmonitorv2/integrations_test.go b/core/services/fluxmonitorv2/integrations_test.go index 7a967300867..6b9dcb99262 100644 --- a/core/services/fluxmonitorv2/integrations_test.go +++ b/core/services/fluxmonitorv2/integrations_test.go @@ -24,9 +24,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/jmoiron/sqlx" - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" @@ -43,7 +42,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/fluxmonitorv2" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -393,32 +391,34 @@ func assertNoSubmission(t *testing.T, // assertPipelineRunCreated checks that a pipeline exists for a given round and // verifies the answer -func assertPipelineRunCreated(t *testing.T, db *sqlx.DB, roundID int64, result int64) pipeline.Run { +func assertPipelineRunCreated(t *testing.T, ds sqlutil.DataSource, roundID int64, result int64) pipeline.Run { + ctx := testutils.Context(t) // Fetch the stats to extract the run id stats := fluxmonitorv2.FluxMonitorRoundStatsV2{} - require.NoError(t, db.Get(&stats, "SELECT * FROM flux_monitor_round_stats_v2 WHERE round_id = $1", roundID)) + require.NoError(t, ds.GetContext(ctx, &stats, "SELECT * FROM flux_monitor_round_stats_v2 WHERE round_id = $1", roundID)) if stats.ID == 0 { t.Fatalf("Stats for round id: %v not found!", roundID) } require.True(t, stats.PipelineRunID.Valid) // Verify the pipeline run data run := pipeline.Run{} - require.NoError(t, db.Get(&run, `SELECT * FROM pipeline_runs WHERE id = $1`, stats.PipelineRunID.Int64), "runID %v", stats.PipelineRunID) + require.NoError(t, ds.GetContext(ctx, &run, `SELECT * FROM pipeline_runs WHERE id = $1`, stats.PipelineRunID.Int64), "runID %v", stats.PipelineRunID) assert.Equal(t, []interface{}{result}, run.Outputs.Val) return run } -func checkLogWasConsumed(t *testing.T, fa fluxAggregatorUniverse, db *sqlx.DB, pipelineSpecID int32, blockNumber uint64, cfg pg.QConfig) { +func checkLogWasConsumed(t *testing.T, fa fluxAggregatorUniverse, ds sqlutil.DataSource, pipelineSpecID int32, blockNumber uint64) { t.Helper() lggr := logger.TestLogger(t) lggr.Infof("Waiting for log on block: %v, job id: %v", blockNumber, pipelineSpecID) g := gomega.NewWithT(t) g.Eventually(func() bool { + ctx := testutils.Context(t) block := fa.backend.Blockchain().GetBlockByNumber(blockNumber) require.NotNil(t, block) - orm := log.NewORM(db, fa.evmChainID) - consumed, err := orm.WasBroadcastConsumed(testutils.Context(t), block.Hash(), 0, pipelineSpecID) + orm := log.NewORM(ds, fa.evmChainID) + consumed, err := orm.WasBroadcastConsumed(ctx, block.Hash(), 0, pipelineSpecID) require.NoError(t, err) fa.backend.Commit() return consumed @@ -559,12 +559,12 @@ func TestFluxMonitor_Deviation(t *testing.T) { initialBalance, receiptBlock, ) - assertPipelineRunCreated(t, app.GetSqlxDB(), 1, int64(100)) + assertPipelineRunCreated(t, app.GetDB(), 1, int64(100)) // Need to wait until NewRound log is consumed - otherwise there is a chance // it will arrive after the next answer is submitted, and cause // DeleteFluxMonitorRoundsBackThrough to delete previous stats - checkLogWasConsumed(t, fa, app.GetSqlxDB(), jobID, receiptBlock, app.GetConfig().Database()) + checkLogWasConsumed(t, fa, app.GetDB(), jobID, receiptBlock) lggr.Info("Updating price to 103") // Change reported price to a value outside the deviation @@ -588,12 +588,12 @@ func TestFluxMonitor_Deviation(t *testing.T) { initialBalance-fee, receiptBlock, ) - assertPipelineRunCreated(t, app.GetSqlxDB(), 2, int64(103)) + assertPipelineRunCreated(t, app.GetDB(), 2, int64(103)) // Need to wait until NewRound log is consumed - otherwise there is a chance // it will arrive after the next answer is submitted, and cause // DeleteFluxMonitorRoundsBackThrough to delete previous stats - checkLogWasConsumed(t, fa, app.GetSqlxDB(), jobID, receiptBlock, app.GetConfig().Database()) + checkLogWasConsumed(t, fa, app.GetDB(), jobID, receiptBlock) // Should not received a submission as it is inside the deviation reportPrice.Store(104) @@ -795,7 +795,7 @@ ds1 -> ds1_parse // node doesn't submit initial response, because flag is up // Wait here so the next lower flags doesn't trigger immediately - cltest.AssertPipelineRunsStays(t, j.PipelineSpec.ID, app.GetSqlxDB(), 0) + cltest.AssertPipelineRunsStays(t, j.PipelineSpec.ID, app.GetDB(), 0) // lower global kill switch flag - should trigger job run _, err = fa.flagsContract.LowerFlags(fa.sergey, []common.Address{evmutils.ZeroAddress}) @@ -910,7 +910,7 @@ ds1 -> ds1_parse jobID, err := strconv.ParseInt(j.ID, 10, 32) require.NoError(t, err) - jse := cltest.WaitForSpecErrorV2(t, app.GetSqlxDB(), int32(jobID), 1) + jse := cltest.WaitForSpecErrorV2(t, app.GetDB(), int32(jobID), 1) assert.Contains(t, jse[0].Description, "Answer is outside acceptable range") } diff --git a/core/services/fluxmonitorv2/orm_test.go b/core/services/fluxmonitorv2/orm_test.go index db00fabb4ff..9652c0b0e27 100644 --- a/core/services/fluxmonitorv2/orm_test.go +++ b/core/services/fluxmonitorv2/orm_test.go @@ -99,14 +99,14 @@ func TestORM_UpdateFluxMonitorRoundStats(t *testing.T) { // Instantiate a real job ORM because we need to create a job to satisfy // a check in pipeline.CreateRun - jobORM := job.NewORM(db, pipelineORM, bridgeORM, keyStore, lggr, cfg.Database()) + jobORM := job.NewORM(db, pipelineORM, bridgeORM, keyStore, lggr) orm := newORM(t, db, nil) address := testutils.NewAddress() var roundID uint32 = 1 jb := makeJob(t) - require.NoError(t, jobORM.CreateJob(jb)) + require.NoError(t, jobORM.CreateJob(ctx, jb)) for expectedCount := uint64(1); expectedCount < 4; expectedCount++ { f := time.Now() diff --git a/core/services/functions/listener_test.go b/core/services/functions/listener_test.go index f3754bbbc29..a1a29bf2500 100644 --- a/core/services/functions/listener_test.go +++ b/core/services/functions/listener_test.go @@ -186,7 +186,7 @@ func TestFunctionsListener_HandleOffchainRequest_Success(t *testing.T) { uni := NewFunctionsListenerUniverse(t, 0, 1_000_000) - uni.pluginORM.On("CreateRequest", mock.Anything, mock.Anything).Return(nil) + uni.pluginORM.On("CreateRequest", mock.Anything, mock.Anything, mock.Anything).Return(nil) uni.bridgeAccessor.On("NewExternalAdapterClient", mock.Anything).Return(uni.eaClient, nil) uni.eaClient.On("RunComputation", mock.Anything, RequestIDStr, mock.Anything, SubscriptionOwner.Hex(), SubscriptionID, mock.Anything, mock.Anything, mock.Anything).Return(ResultBytes, nil, nil, nil) uni.pluginORM.On("SetResult", mock.Anything, RequestID, ResultBytes, mock.Anything, mock.Anything).Return(nil) @@ -230,7 +230,7 @@ func TestFunctionsListener_HandleOffchainRequest_InternalError(t *testing.T) { testutils.SkipShortDB(t) t.Parallel() uni := NewFunctionsListenerUniverse(t, 0, 1_000_000) - uni.pluginORM.On("CreateRequest", mock.Anything, mock.Anything).Return(nil) + uni.pluginORM.On("CreateRequest", mock.Anything, mock.Anything, mock.Anything).Return(nil) uni.bridgeAccessor.On("NewExternalAdapterClient", mock.Anything).Return(uni.eaClient, nil) uni.eaClient.On("RunComputation", mock.Anything, RequestIDStr, mock.Anything, SubscriptionOwner.Hex(), SubscriptionID, mock.Anything, mock.Anything, mock.Anything).Return(nil, nil, nil, errors.New("error")) uni.pluginORM.On("SetError", mock.Anything, RequestID, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) diff --git a/core/services/gateway/delegate.go b/core/services/gateway/delegate.go index 8cddc027803..5a30228db4c 100644 --- a/core/services/gateway/delegate.go +++ b/core/services/gateway/delegate.go @@ -5,34 +5,31 @@ import ( "encoding/json" "github.com/google/uuid" - "github.com/jmoiron/sqlx" "github.com/pelletier/go-toml" "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/config" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) type Delegate struct { legacyChains legacyevm.LegacyChainContainer ks keystore.Eth - db *sqlx.DB - cfg pg.QConfig + ds sqlutil.DataSource lggr logger.Logger } var _ job.Delegate = (*Delegate)(nil) -func NewDelegate(legacyChains legacyevm.LegacyChainContainer, ks keystore.Eth, db *sqlx.DB, cfg pg.QConfig, lggr logger.Logger) *Delegate { +func NewDelegate(legacyChains legacyevm.LegacyChainContainer, ks keystore.Eth, ds sqlutil.DataSource, lggr logger.Logger) *Delegate { return &Delegate{ legacyChains: legacyChains, ks: ks, - db: db, - cfg: cfg, + ds: ds, lggr: lggr, } } @@ -57,7 +54,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services if err2 != nil { return nil, errors.Wrap(err2, "unmarshal gateway config") } - handlerFactory := NewHandlerFactory(d.legacyChains, d.db, d.cfg, d.lggr) + handlerFactory := NewHandlerFactory(d.legacyChains, d.ds, d.lggr) gateway, err := NewGatewayFromConfig(&gatewayConfig, handlerFactory, d.lggr) if err != nil { return nil, err diff --git a/core/services/gateway/gateway_test.go b/core/services/gateway/gateway_test.go index 7a5457c788c..3218c5428a2 100644 --- a/core/services/gateway/gateway_test.go +++ b/core/services/gateway/gateway_test.go @@ -57,7 +57,7 @@ Address = "0x0001020304050607080900010203040506070809" `) lggr := logger.TestLogger(t) - _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, lggr), lggr) require.NoError(t, err) } @@ -75,7 +75,7 @@ HandlerName = "dummy" `) lggr := logger.TestLogger(t) - _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, lggr), lggr) require.Error(t, err) } @@ -89,7 +89,7 @@ HandlerName = "no_such_handler" `) lggr := logger.TestLogger(t) - _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, lggr), lggr) require.Error(t, err) } @@ -103,7 +103,7 @@ SomeOtherField = "abcd" `) lggr := logger.TestLogger(t) - _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, lggr), lggr) require.Error(t, err) } @@ -121,7 +121,7 @@ Address = "0xnot_an_address" `) lggr := logger.TestLogger(t) - _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) + _, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, tomlConfig), gateway.NewHandlerFactory(nil, nil, lggr), lggr) require.Error(t, err) } @@ -129,7 +129,7 @@ func TestGateway_CleanStartAndClose(t *testing.T) { t.Parallel() lggr := logger.TestLogger(t) - gateway, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, buildConfig("")), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) + gateway, err := gateway.NewGatewayFromConfig(parseTOMLConfig(t, buildConfig("")), gateway.NewHandlerFactory(nil, nil, lggr), lggr) require.NoError(t, err) servicetest.Run(t, gateway) } diff --git a/core/services/gateway/handler_factory.go b/core/services/gateway/handler_factory.go index 8ccae8c7c4b..ca6b98e55aa 100644 --- a/core/services/gateway/handler_factory.go +++ b/core/services/gateway/handler_factory.go @@ -4,14 +4,12 @@ import ( "encoding/json" "fmt" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/config" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) const ( @@ -21,21 +19,20 @@ const ( type handlerFactory struct { legacyChains legacyevm.LegacyChainContainer - db *sqlx.DB - cfg pg.QConfig + ds sqlutil.DataSource lggr logger.Logger } var _ HandlerFactory = (*handlerFactory)(nil) -func NewHandlerFactory(legacyChains legacyevm.LegacyChainContainer, db *sqlx.DB, cfg pg.QConfig, lggr logger.Logger) HandlerFactory { - return &handlerFactory{legacyChains, db, cfg, lggr} +func NewHandlerFactory(legacyChains legacyevm.LegacyChainContainer, ds sqlutil.DataSource, lggr logger.Logger) HandlerFactory { + return &handlerFactory{legacyChains, ds, lggr} } func (hf *handlerFactory) NewHandler(handlerType HandlerType, handlerConfig json.RawMessage, donConfig *config.DONConfig, don handlers.DON) (handlers.Handler, error) { switch handlerType { case FunctionsHandlerType: - return functions.NewFunctionsHandlerFromConfig(handlerConfig, donConfig, don, hf.legacyChains, hf.db, hf.cfg, hf.lggr) + return functions.NewFunctionsHandlerFromConfig(handlerConfig, donConfig, don, hf.legacyChains, hf.ds, hf.lggr) case DummyHandlerType: return handlers.NewDummyHandler(donConfig, don, hf.lggr) default: diff --git a/core/services/gateway/handlers/functions/handler.functions.go b/core/services/gateway/handlers/functions/handler.functions.go index 692534db598..2d55bb23fde 100644 --- a/core/services/gateway/handlers/functions/handler.functions.go +++ b/core/services/gateway/handlers/functions/handler.functions.go @@ -10,13 +10,13 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/jmoiron/sqlx" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "go.uber.org/multierr" "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" @@ -25,7 +25,6 @@ import ( hc "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" fallow "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions/allowlist" fsub "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions/subscriptions" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) var ( @@ -100,7 +99,7 @@ type PendingRequest struct { var _ handlers.Handler = (*functionsHandler)(nil) -func NewFunctionsHandlerFromConfig(handlerConfig json.RawMessage, donConfig *config.DONConfig, don handlers.DON, legacyChains legacyevm.LegacyChainContainer, db *sqlx.DB, qcfg pg.QConfig, lggr logger.Logger) (handlers.Handler, error) { +func NewFunctionsHandlerFromConfig(handlerConfig json.RawMessage, donConfig *config.DONConfig, don handlers.DON, legacyChains legacyevm.LegacyChainContainer, ds sqlutil.DataSource, lggr logger.Logger) (handlers.Handler, error) { var cfg FunctionsHandlerConfig err := json.Unmarshal(handlerConfig, &cfg) if err != nil { @@ -114,7 +113,7 @@ func NewFunctionsHandlerFromConfig(handlerConfig json.RawMessage, donConfig *con return nil, err2 } - orm, err2 := fallow.NewORM(db, lggr, cfg.OnchainAllowlist.ContractAddress) + orm, err2 := fallow.NewORM(ds, lggr, cfg.OnchainAllowlist.ContractAddress) if err2 != nil { return nil, err2 } @@ -143,7 +142,7 @@ func NewFunctionsHandlerFromConfig(handlerConfig json.RawMessage, donConfig *con return nil, err2 } - orm, err2 := fsub.NewORM(db, lggr, cfg.OnchainSubscriptions.ContractAddress) + orm, err2 := fsub.NewORM(ds, lggr, cfg.OnchainSubscriptions.ContractAddress) if err2 != nil { return nil, err2 } diff --git a/core/services/gateway/handlers/functions/handler.functions_test.go b/core/services/gateway/handlers/functions/handler.functions_test.go index 2e2c1c77caf..b7abeed8a99 100644 --- a/core/services/gateway/handlers/functions/handler.functions_test.go +++ b/core/services/gateway/handlers/functions/handler.functions_test.go @@ -84,7 +84,7 @@ func sendNodeReponses(t *testing.T, handler handlers.Handler, userRequestMsg api func TestFunctionsHandler_Minimal(t *testing.T) { t.Parallel() - handler, err := functions.NewFunctionsHandlerFromConfig(json.RawMessage("{}"), &config.DONConfig{}, nil, nil, nil, nil, logger.TestLogger(t)) + handler, err := functions.NewFunctionsHandlerFromConfig(json.RawMessage("{}"), &config.DONConfig{}, nil, nil, nil, logger.TestLogger(t)) require.NoError(t, err) // empty message should always error out @@ -96,7 +96,7 @@ func TestFunctionsHandler_Minimal(t *testing.T) { func TestFunctionsHandler_CleanStartAndClose(t *testing.T) { t.Parallel() - handler, err := functions.NewFunctionsHandlerFromConfig(json.RawMessage("{}"), &config.DONConfig{}, nil, nil, nil, nil, logger.TestLogger(t)) + handler, err := functions.NewFunctionsHandlerFromConfig(json.RawMessage("{}"), &config.DONConfig{}, nil, nil, nil, logger.TestLogger(t)) require.NoError(t, err) servicetest.Run(t, handler) diff --git a/core/services/gateway/integration_tests/gateway_integration_test.go b/core/services/gateway/integration_tests/gateway_integration_test.go index 7f4a2ab58fa..38a6b6ebbca 100644 --- a/core/services/gateway/integration_tests/gateway_integration_test.go +++ b/core/services/gateway/integration_tests/gateway_integration_test.go @@ -143,7 +143,7 @@ func TestIntegration_Gateway_NoFullNodes_BasicConnectionAndMessage(t *testing.T) // Launch Gateway lggr := logger.TestLogger(t) gatewayConfig := fmt.Sprintf(gatewayConfigTemplate, nodeKeys.Address) - gateway, err := gateway.NewGatewayFromConfig(parseGatewayConfig(t, gatewayConfig), gateway.NewHandlerFactory(nil, nil, nil, lggr), lggr) + gateway, err := gateway.NewGatewayFromConfig(parseGatewayConfig(t, gatewayConfig), gateway.NewHandlerFactory(nil, nil, lggr), lggr) require.NoError(t, err) servicetest.Run(t, gateway) userPort, nodePort := gateway.GetUserPort(), gateway.GetNodePort() diff --git a/core/services/job/common.go b/core/services/job/common.go index 58b1754cbf5..055195440b0 100644 --- a/core/services/job/common.go +++ b/core/services/job/common.go @@ -3,8 +3,6 @@ package job import ( "context" "net/url" - - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) //go:generate mockery --quiet --name ServiceCtx --output ./mocks/ --case=underscore @@ -22,7 +20,6 @@ type ServiceCtx interface { type Config interface { URL() url.URL - pg.QConfig } // ServiceAdapter is a helper introduced for transitioning from Service to ServiceCtx. diff --git a/core/services/job/helpers_test.go b/core/services/job/helpers_test.go index 22e1b0bef63..7120fe4200c 100644 --- a/core/services/job/helpers_test.go +++ b/core/services/job/helpers_test.go @@ -268,8 +268,7 @@ func makeOCRJobSpecFromToml(t *testing.T, jobSpecToml string) *job.Job { return &jb } -func makeOCR2VRFJobSpec(t testing.TB, ks keystore.Master, cfg chainlink.GeneralConfig, - transmitter common.Address, chainID *big.Int, fromBlock uint64) *job.Job { +func makeOCR2VRFJobSpec(t testing.TB, ks keystore.Master, transmitter common.Address, chainID *big.Int, fromBlock uint64) *job.Job { t.Helper() ctx := testutils.Context(t) diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index ffbd02c512b..f07b68d9987 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -73,20 +73,21 @@ serverPubKey = '8fa807463ad73f9ee855cfd60ba406dcf98a2855b3dd8af613107b0f6890a707 func TestORM(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) + config := configtest.NewTestGeneralConfig(t) db := pgtest.NewSqlxDB(t) keyStore := cltest.NewKeyStore(t, db) ethKeyStore := keyStore.Eth() - require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) - require.NoError(t, keyStore.P2P().Add(ctx, cltest.DefaultP2PKey)) + func() { + ctx := testutils.Context(t) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) + require.NoError(t, keyStore.P2P().Add(ctx, cltest.DefaultP2PKey)) + }() pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) - bridgesORM := bridges.NewORM(db) - - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) borm := bridges.NewORM(db) + orm := NewTestORM(t, db, pipelineORM, borm, keyStore) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -94,7 +95,7 @@ func TestORM(t *testing.T) { jb := makeOCRJobSpec(t, address, bridge.Name.String(), bridge2.Name.String()) t.Run("it creates job specs", func(t *testing.T) { - err := orm.CreateJob(jb) + err := orm.CreateJob(testutils.Context(t), jb) require.NoError(t, err) var returnedSpec job.Job @@ -109,8 +110,9 @@ func TestORM(t *testing.T) { }) t.Run("it correctly mark job_pipeline_specs as primary when creating a job", func(t *testing.T) { + ctx := testutils.Context(t) jb2 := makeOCRJobSpec(t, address, bridge.Name.String(), bridge2.Name.String()) - err := orm.CreateJob(jb2) + err := orm.CreateJob(ctx, jb2) require.NoError(t, err) var pipelineSpec pipeline.Spec @@ -128,7 +130,7 @@ func TestORM(t *testing.T) { t.Run("autogenerates external job ID if missing", func(t *testing.T) { jb2 := makeOCRJobSpec(t, address, bridge.Name.String(), bridge2.Name.String()) jb2.ExternalJobID = uuid.UUID{} - err := orm.CreateJob(jb2) + err := orm.CreateJob(testutils.Context(t), jb2) require.NoError(t, err) var returnedSpec job.Job @@ -145,7 +147,7 @@ func TestORM(t *testing.T) { require.NoError(t, err) require.Len(t, dbSpecs, 3) - err = orm.DeleteJob(jb.ID) + err = orm.DeleteJob(testutils.Context(t), jb.ID) require.NoError(t, err) dbSpecs = []job.Job{} @@ -155,8 +157,9 @@ func TestORM(t *testing.T) { }) t.Run("increase job spec error occurrence", func(t *testing.T) { + ctx := testutils.Context(t) jb3 := makeOCRJobSpec(t, address, bridge.Name.String(), bridge2.Name.String()) - err := orm.CreateJob(jb3) + err := orm.CreateJob(ctx, jb3) require.NoError(t, err) var jobSpec job.Job err = db.Get(&jobSpec, "SELECT * FROM jobs") @@ -164,9 +167,9 @@ func TestORM(t *testing.T) { ocrSpecError1 := "ocr spec 1 errored" ocrSpecError2 := "ocr spec 2 errored" - require.NoError(t, orm.RecordError(jobSpec.ID, ocrSpecError1)) - require.NoError(t, orm.RecordError(jobSpec.ID, ocrSpecError1)) - require.NoError(t, orm.RecordError(jobSpec.ID, ocrSpecError2)) + require.NoError(t, orm.RecordError(ctx, jobSpec.ID, ocrSpecError1)) + require.NoError(t, orm.RecordError(ctx, jobSpec.ID, ocrSpecError1)) + require.NoError(t, orm.RecordError(ctx, jobSpec.ID, ocrSpecError2)) var specErrors []job.SpecError err = db.Select(&specErrors, "SELECT * FROM job_spec_errors") @@ -193,8 +196,9 @@ func TestORM(t *testing.T) { }) t.Run("finds job spec error by ID", func(t *testing.T) { + ctx := testutils.Context(t) jb3 := makeOCRJobSpec(t, address, bridge.Name.String(), bridge2.Name.String()) - err := orm.CreateJob(jb3) + err := orm.CreateJob(ctx, jb3) require.NoError(t, err) var jobSpec job.Job err = db.Get(&jobSpec, "SELECT * FROM jobs") @@ -207,8 +211,8 @@ func TestORM(t *testing.T) { ocrSpecError1 := "ocr spec 3 errored" ocrSpecError2 := "ocr spec 4 errored" - require.NoError(t, orm.RecordError(jobSpec.ID, ocrSpecError1)) - require.NoError(t, orm.RecordError(jobSpec.ID, ocrSpecError2)) + require.NoError(t, orm.RecordError(ctx, jobSpec.ID, ocrSpecError1)) + require.NoError(t, orm.RecordError(ctx, jobSpec.ID, ocrSpecError2)) var updatedSpecError []job.SpecError @@ -221,9 +225,9 @@ func TestORM(t *testing.T) { assert.Equal(t, ocrSpecError1, updatedSpecError[2].Description) assert.Equal(t, ocrSpecError2, updatedSpecError[3].Description) - dbSpecErr1, err := orm.FindSpecError(updatedSpecError[2].ID) + dbSpecErr1, err := orm.FindSpecError(ctx, updatedSpecError[2].ID) require.NoError(t, err) - dbSpecErr2, err := orm.FindSpecError(updatedSpecError[3].ID) + dbSpecErr2, err := orm.FindSpecError(ctx, updatedSpecError[3].ID) require.NoError(t, err) assert.Equal(t, uint(1), dbSpecErr1.Occurrences) @@ -251,11 +255,12 @@ func TestORM(t *testing.T) { drJob, err := directrequest.ValidatedDirectRequestSpec(drSpec) require.NoError(t, err) - err = orm.CreateJob(&drJob) + err = orm.CreateJob(testutils.Context(t), &drJob) require.NoError(t, err) }) t.Run("creates webhook specs along with external_initiator_webhook_specs", func(t *testing.T) { + ctx := testutils.Context(t) eiFoo := cltest.MustInsertExternalInitiator(t, borm) eiBar := cltest.MustInsertExternalInitiator(t, borm) @@ -263,22 +268,23 @@ func TestORM(t *testing.T) { {Name: eiFoo.Name, Spec: cltest.JSONFromString(t, `{}`)}, {Name: eiBar.Name, Spec: cltest.JSONFromString(t, `{"bar": 1}`)}, } - eim := webhook.NewExternalInitiatorManager(db, nil, logger.TestLogger(t), config.Database()) - jb, err := webhook.ValidatedWebhookSpec(testspecs.GenerateWebhookSpec(testspecs.WebhookSpecParams{ExternalInitiators: eiWS}).Toml(), eim) + eim := webhook.NewExternalInitiatorManager(db, nil) + jb, err := webhook.ValidatedWebhookSpec(ctx, testspecs.GenerateWebhookSpec(testspecs.WebhookSpecParams{ExternalInitiators: eiWS}).Toml(), eim) require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) cltest.AssertCount(t, db, "external_initiator_webhook_specs", 2) }) t.Run("it creates and deletes records for blockhash store jobs", func(t *testing.T) { + ctx := testutils.Context(t) bhsJob, err := blockhashstore.ValidatedSpec( testspecs.GenerateBlockhashStoreSpec(testspecs.BlockhashStoreSpecParams{}).Toml()) require.NoError(t, err) - err = orm.CreateJob(&bhsJob) + err = orm.CreateJob(ctx, &bhsJob) require.NoError(t, err) savedJob, err := orm.FindJob(testutils.Context(t), bhsJob.ID) require.NoError(t, err) @@ -298,18 +304,19 @@ func TestORM(t *testing.T) { require.Equal(t, bhsJob.BlockhashStoreSpec.RunTimeout, savedJob.BlockhashStoreSpec.RunTimeout) require.Equal(t, bhsJob.BlockhashStoreSpec.EVMChainID, savedJob.BlockhashStoreSpec.EVMChainID) require.Equal(t, bhsJob.BlockhashStoreSpec.FromAddresses, savedJob.BlockhashStoreSpec.FromAddresses) - err = orm.DeleteJob(bhsJob.ID) + err = orm.DeleteJob(ctx, bhsJob.ID) require.NoError(t, err) _, err = orm.FindJob(testutils.Context(t), bhsJob.ID) require.Error(t, err) }) t.Run("it creates and deletes records for blockheaderfeeder jobs", func(t *testing.T) { + ctx := testutils.Context(t) bhsJob, err := blockheaderfeeder.ValidatedSpec( testspecs.GenerateBlockHeaderFeederSpec(testspecs.BlockHeaderFeederSpecParams{}).Toml()) require.NoError(t, err) - err = orm.CreateJob(&bhsJob) + err = orm.CreateJob(ctx, &bhsJob) require.NoError(t, err) savedJob, err := orm.FindJob(testutils.Context(t), bhsJob.ID) require.NoError(t, err) @@ -329,7 +336,7 @@ func TestORM(t *testing.T) { require.Equal(t, bhsJob.BlockHeaderFeederSpec.FromAddresses, savedJob.BlockHeaderFeederSpec.FromAddresses) require.Equal(t, bhsJob.BlockHeaderFeederSpec.GetBlockhashesBatchSize, savedJob.BlockHeaderFeederSpec.GetBlockhashesBatchSize) require.Equal(t, bhsJob.BlockHeaderFeederSpec.StoreBlockhashesBatchSize, savedJob.BlockHeaderFeederSpec.StoreBlockhashesBatchSize) - err = orm.DeleteJob(bhsJob.ID) + err = orm.DeleteJob(ctx, bhsJob.ID) require.NoError(t, err) _, err = orm.FindJob(testutils.Context(t), bhsJob.ID) require.Error(t, err) @@ -349,10 +356,11 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) { lggr := logger.TestLogger(t) pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) korm := keeper.NewORM(db, logger.TestLogger(t)) t.Run("it deletes records for offchainreporting jobs", func(t *testing.T) { + ctx := testutils.Context(t) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -366,13 +374,13 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) { }).Toml()) require.NoError(t, err) - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(ctx, &jb) require.NoError(t, err) cltest.AssertCount(t, db, "ocr_oracle_specs", 1) cltest.AssertCount(t, db, "pipeline_specs", 1) - err = jobORM.DeleteJob(jb.ID) + err = jobORM.DeleteJob(ctx, jb.ID) require.NoError(t, err) cltest.AssertCount(t, db, "ocr_oracle_specs", 0) cltest.AssertCount(t, db, "pipeline_specs", 0) @@ -380,6 +388,7 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) { }) t.Run("it deletes records for keeper jobs", func(t *testing.T) { + ctx := testutils.Context(t) registry, keeperJob := cltest.MustInsertKeeperRegistry(t, db, korm, keyStore.Eth(), 0, 1, 20) cltest.MustInsertUpkeepForRegistry(t, db, registry) @@ -387,7 +396,7 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) { cltest.AssertCount(t, db, "keeper_registries", 1) cltest.AssertCount(t, db, "upkeep_registrations", 1) - err := jobORM.DeleteJob(keeperJob.ID) + err := jobORM.DeleteJob(ctx, keeperJob.ID) require.NoError(t, err) cltest.AssertCount(t, db, "keeper_specs", 0) cltest.AssertCount(t, db, "keeper_registries", 0) @@ -396,29 +405,31 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) { }) t.Run("it creates and deletes records for vrf jobs", func(t *testing.T) { - key, err := keyStore.VRF().Create(testutils.Context(t)) + ctx := testutils.Context(t) + key, err := keyStore.VRF().Create(ctx) require.NoError(t, err) pk := key.PublicKey jb, err := vrfcommon.ValidatedVRFSpec(testspecs.GenerateVRFSpec(testspecs.VRFSpecParams{PublicKey: pk.String()}).Toml()) require.NoError(t, err) - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(ctx, &jb) require.NoError(t, err) cltest.AssertCount(t, db, "vrf_specs", 1) cltest.AssertCount(t, db, "jobs", 1) - err = jobORM.DeleteJob(jb.ID) + err = jobORM.DeleteJob(ctx, jb.ID) require.NoError(t, err) cltest.AssertCount(t, db, "vrf_specs", 0) cltest.AssertCount(t, db, "jobs", 0) }) t.Run("it deletes records for webhook jobs", func(t *testing.T) { + ctx := testutils.Context(t) ei := cltest.MustInsertExternalInitiator(t, bridges.NewORM(db)) jb, webhookSpec := cltest.MustInsertWebhookSpec(t, db) _, err := db.Exec(`INSERT INTO external_initiator_webhook_specs (external_initiator_id, webhook_spec_id, spec) VALUES ($1,$2,$3)`, ei.ID, webhookSpec.ID, `{"ei": "foo", "name": "webhookSpecTwoEIs"}`) require.NoError(t, err) - err = jobORM.DeleteJob(jb.ID) + err = jobORM.DeleteJob(ctx, jb.ID) require.NoError(t, err) cltest.AssertCount(t, db, "webhook_specs", 0) cltest.AssertCount(t, db, "external_initiator_webhook_specs", 0) @@ -449,7 +460,7 @@ func TestORM_CreateJob_VRFV2(t *testing.T) { pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) fromAddresses := []string{cltest.NewEIP55Address().String(), cltest.NewEIP55Address().String()} jb, err := vrfcommon.ValidatedVRFSpec(testspecs.GenerateVRFSpec( @@ -465,7 +476,7 @@ func TestORM_CreateJob_VRFV2(t *testing.T) { Toml()) require.NoError(t, err) - require.NoError(t, jobORM.CreateJob(&jb)) + require.NoError(t, jobORM.CreateJob(ctx, &jb)) cltest.AssertCount(t, db, "vrf_specs", 1) cltest.AssertCount(t, db, "jobs", 1) var requestedConfsDelay int64 @@ -505,20 +516,20 @@ func TestORM_CreateJob_VRFV2(t *testing.T) { var vrfOwnerAddress evmtypes.EIP55Address require.NoError(t, db.Get(&vrfOwnerAddress, `SELECT vrf_owner_address FROM vrf_specs LIMIT 1`)) require.Equal(t, "0x32891BD79647DC9136Fc0a59AAB48c7825eb624c", vrfOwnerAddress.Address().String()) - require.NoError(t, jobORM.DeleteJob(jb.ID)) + require.NoError(t, jobORM.DeleteJob(ctx, jb.ID)) cltest.AssertCount(t, db, "vrf_specs", 0) cltest.AssertCount(t, db, "jobs", 0) jb, err = vrfcommon.ValidatedVRFSpec(testspecs.GenerateVRFSpec(testspecs.VRFSpecParams{RequestTimeout: 1 * time.Hour}).Toml()) require.NoError(t, err) - require.NoError(t, jobORM.CreateJob(&jb)) + require.NoError(t, jobORM.CreateJob(ctx, &jb)) cltest.AssertCount(t, db, "vrf_specs", 1) cltest.AssertCount(t, db, "jobs", 1) require.NoError(t, db.Get(&requestedConfsDelay, `SELECT requested_confs_delay FROM vrf_specs LIMIT 1`)) require.Equal(t, int64(0), requestedConfsDelay) require.NoError(t, db.Get(&requestTimeout, `SELECT request_timeout FROM vrf_specs LIMIT 1`)) require.Equal(t, 1*time.Hour, requestTimeout) - require.NoError(t, jobORM.DeleteJob(jb.ID)) + require.NoError(t, jobORM.DeleteJob(ctx, jb.ID)) cltest.AssertCount(t, db, "vrf_specs", 0) cltest.AssertCount(t, db, "jobs", 0) } @@ -533,7 +544,7 @@ func TestORM_CreateJob_VRFV2Plus(t *testing.T) { lggr := logger.TestLogger(t) pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) fromAddresses := []string{cltest.NewEIP55Address().String(), cltest.NewEIP55Address().String()} jb, err := vrfcommon.ValidatedVRFSpec(testspecs.GenerateVRFSpec( @@ -550,7 +561,7 @@ func TestORM_CreateJob_VRFV2Plus(t *testing.T) { Toml()) require.NoError(t, err) - require.NoError(t, jobORM.CreateJob(&jb)) + require.NoError(t, jobORM.CreateJob(ctx, &jb)) cltest.AssertCount(t, db, "vrf_specs", 1) cltest.AssertCount(t, db, "jobs", 1) var requestedConfsDelay int64 @@ -589,7 +600,7 @@ func TestORM_CreateJob_VRFV2Plus(t *testing.T) { require.ElementsMatch(t, fromAddresses, actual) var vrfOwnerAddress evmtypes.EIP55Address require.Error(t, db.Get(&vrfOwnerAddress, `SELECT vrf_owner_address FROM vrf_specs LIMIT 1`)) - require.NoError(t, jobORM.DeleteJob(jb.ID)) + require.NoError(t, jobORM.DeleteJob(ctx, jb.ID)) cltest.AssertCount(t, db, "vrf_specs", 0) cltest.AssertCount(t, db, "jobs", 0) @@ -599,14 +610,14 @@ func TestORM_CreateJob_VRFV2Plus(t *testing.T) { FromAddresses: fromAddresses, }).Toml()) require.NoError(t, err) - require.NoError(t, jobORM.CreateJob(&jb)) + require.NoError(t, jobORM.CreateJob(ctx, &jb)) cltest.AssertCount(t, db, "vrf_specs", 1) cltest.AssertCount(t, db, "jobs", 1) require.NoError(t, db.Get(&requestedConfsDelay, `SELECT requested_confs_delay FROM vrf_specs LIMIT 1`)) require.Equal(t, int64(0), requestedConfsDelay) require.NoError(t, db.Get(&requestTimeout, `SELECT request_timeout FROM vrf_specs LIMIT 1`)) require.Equal(t, 1*time.Hour, requestTimeout) - require.NoError(t, jobORM.DeleteJob(jb.ID)) + require.NoError(t, jobORM.DeleteJob(ctx, jb.ID)) cltest.AssertCount(t, db, "vrf_specs", 0) cltest.AssertCount(t, db, "jobs", 0) } @@ -621,12 +632,12 @@ func TestORM_CreateJob_OCRBootstrap(t *testing.T) { lggr := logger.TestLogger(t) pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) jb, err := ocrbootstrap.ValidatedBootstrapSpecToml(testspecs.GetOCRBootstrapSpec()) require.NoError(t, err) - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(ctx, &jb) require.NoError(t, err) cltest.AssertCount(t, db, "bootstrap_specs", 1) cltest.AssertCount(t, db, "jobs", 1) @@ -634,7 +645,7 @@ func TestORM_CreateJob_OCRBootstrap(t *testing.T) { require.NoError(t, db.Get(&relay, `SELECT relay FROM bootstrap_specs LIMIT 1`)) require.Equal(t, "evm", relay) - require.NoError(t, jobORM.DeleteJob(jb.ID)) + require.NoError(t, jobORM.DeleteJob(ctx, jb.ID)) cltest.AssertCount(t, db, "bootstrap_specs", 0) cltest.AssertCount(t, db, "jobs", 0) } @@ -648,14 +659,14 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) t.Run("evm chain id validation for ocr works", func(t *testing.T) { jb := job.Job{ Type: job.OffchainReporting, OCROracleSpec: &job.OCROracleSpec{}, } - assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) }) t.Run("evm chain id validation for direct request works", func(t *testing.T) { @@ -663,7 +674,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { Type: job.DirectRequest, DirectRequestSpec: &job.DirectRequestSpec{}, } - assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) }) t.Run("evm chain id validation for flux monitor works", func(t *testing.T) { @@ -671,7 +682,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { Type: job.FluxMonitor, FluxMonitorSpec: &job.FluxMonitorSpec{}, } - assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) }) t.Run("evm chain id validation for keepers works", func(t *testing.T) { @@ -679,7 +690,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { Type: job.Keeper, KeeperSpec: &job.KeeperSpec{}, } - assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) }) t.Run("evm chain id validation for vrf works", func(t *testing.T) { @@ -687,7 +698,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { Type: job.VRF, VRFSpec: &job.VRFSpec{}, } - assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) }) t.Run("evm chain id validation for block hash store works", func(t *testing.T) { @@ -695,7 +706,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { Type: job.BlockhashStore, BlockhashStoreSpec: &job.BlockhashStoreSpec{}, } - assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) }) t.Run("evm chain id validation for block header feeder works", func(t *testing.T) { @@ -703,7 +714,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { Type: job.BlockHeaderFeeder, BlockHeaderFeederSpec: &job.BlockHeaderFeederSpec{}, } - assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) }) t.Run("evm chain id validation for legacy gas station server spec works", func(t *testing.T) { @@ -711,7 +722,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { Type: job.LegacyGasStationServer, LegacyGasStationServerSpec: &job.LegacyGasStationServerSpec{}, } - assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) }) t.Run("evm chain id validation for legacy gas station sidecar spec works", func(t *testing.T) { @@ -719,7 +730,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { Type: job.LegacyGasStationSidecar, LegacyGasStationSidecarSpec: &job.LegacyGasStationSidecarSpec{}, } - assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: evm chain id must be defined", jobORM.CreateJob(testutils.Context(t), &jb).Error()) }) } @@ -744,7 +755,7 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) { pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) // defaultChainID is deprecated defaultChainID := customChainID @@ -768,7 +779,8 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) { require.NoError(t, err) t.Run("with a set chain id", func(t *testing.T) { - err = jobORM.CreateJob(&jb) // Add job with custom chain id + ctx := testutils.Context(t) + err = jobORM.CreateJob(ctx, &jb) // Add job with custom chain id require.NoError(t, err) cltest.AssertCount(t, db, "ocr_oracle_specs", 1) @@ -778,7 +790,7 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) { spec.JobID = externalJobID.UUID.String() jba, err := ocr.ValidatedOracleSpecToml(config, legacyChains, spec.Toml()) require.NoError(t, err) - err = jobORM.CreateJob(&jba) // Try to add duplicate job with default id + err = jobORM.CreateJob(ctx, &jba) // Try to add duplicate job with default id require.Error(t, err) assert.Equal(t, fmt.Sprintf("CreateJobFailed: a job with contract address %s already exists for chain ID %s", jb.OCROracleSpec.ContractAddress, defaultChainID.String()), err.Error()) @@ -787,7 +799,7 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) { jb2, err := ocr.ValidatedOracleSpecToml(config, legacyChains, spec.Toml()) require.NoError(t, err) - err = jobORM.CreateJob(&jb2) // Try to add duplicate job with custom id + err = jobORM.CreateJob(ctx, &jb2) // Try to add duplicate job with custom id require.Error(t, err) assert.Equal(t, fmt.Sprintf("CreateJobFailed: a job with contract address %s already exists for chain ID %s", jb2.OCROracleSpec.ContractAddress, customChainID), err.Error()) }) @@ -814,7 +826,7 @@ func TestORM_CreateJob_OCR2_DuplicatedContractAddress(t *testing.T) { pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, address := cltest.MustInsertRandomKey(t, keyStore.Eth()) @@ -831,7 +843,7 @@ func TestORM_CreateJob_OCR2_DuplicatedContractAddress(t *testing.T) { jb.OCR2OracleSpec.TransmitterID = null.StringFrom(address.String()) jb.OCR2OracleSpec.PluginConfig["juelsPerFeeCoinSource"] = juelsPerFeeCoinSource - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(ctx, &jb) require.NoError(t, err) jb2, err := ocr2validate.ValidatedOracleSpecToml(testutils.Context(t), config.OCR2(), config.Insecure(), testspecs.GetOCR2EVMSpecMinimal(), nil) @@ -841,7 +853,7 @@ func TestORM_CreateJob_OCR2_DuplicatedContractAddress(t *testing.T) { jb2.OCR2OracleSpec.TransmitterID = null.StringFrom(address.String()) jb.OCR2OracleSpec.PluginConfig["juelsPerFeeCoinSource"] = juelsPerFeeCoinSource - err = jobORM.CreateJob(&jb2) + err = jobORM.CreateJob(ctx, &jb2) require.Error(t, err) jb3, err := ocr2validate.ValidatedOracleSpecToml(testutils.Context(t), config.OCR2(), config.Insecure(), testspecs.GetOCR2EVMSpecMinimal(), nil) @@ -851,7 +863,7 @@ func TestORM_CreateJob_OCR2_DuplicatedContractAddress(t *testing.T) { jb3.OCR2OracleSpec.RelayConfig["chainID"] = customChainID.Int64() jb.OCR2OracleSpec.PluginConfig["juelsPerFeeCoinSource"] = juelsPerFeeCoinSource - err = jobORM.CreateJob(&jb3) + err = jobORM.CreateJob(ctx, &jb3) require.Error(t, err) } @@ -876,37 +888,41 @@ func TestORM_CreateJob_OCR2_Sending_Keys_Transmitter_Keys_Validations(t *testing pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) jb, err := ocr2validate.ValidatedOracleSpecToml(testutils.Context(t), config.OCR2(), config.Insecure(), testspecs.GetOCR2EVMSpecMinimal(), nil) require.NoError(t, err) t.Run("sending keys or transmitterID must be defined", func(t *testing.T) { + ctx := testutils.Context(t) jb.OCR2OracleSpec.TransmitterID = null.String{} - assert.Equal(t, "CreateJobFailed: neither sending keys nor transmitter ID is defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: neither sending keys nor transmitter ID is defined", jobORM.CreateJob(ctx, &jb).Error()) }) _, address := cltest.MustInsertRandomKey(t, keyStore.Eth()) t.Run("sending keys validation works properly", func(t *testing.T) { + ctx := testutils.Context(t) jb.OCR2OracleSpec.TransmitterID = null.String{} _, address2 := cltest.MustInsertRandomKey(t, keyStore.Eth()) jb.OCR2OracleSpec.RelayConfig["sendingKeys"] = interface{}([]any{address.String(), address2.String(), common.HexToAddress("0X0").String()}) - assert.Equal(t, "CreateJobFailed: no EVM key matching: \"0x0000000000000000000000000000000000000000\": no such sending key exists", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: no EVM key matching: \"0x0000000000000000000000000000000000000000\": no such sending key exists", jobORM.CreateJob(ctx, &jb).Error()) jb.OCR2OracleSpec.RelayConfig["sendingKeys"] = interface{}([]any{1, 2, 3}) - assert.Equal(t, "CreateJobFailed: sending keys are of wrong type", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: sending keys are of wrong type", jobORM.CreateJob(ctx, &jb).Error()) }) t.Run("sending keys and transmitter ID can't both be defined", func(t *testing.T) { + ctx := testutils.Context(t) jb.OCR2OracleSpec.TransmitterID = null.StringFrom(address.String()) jb.OCR2OracleSpec.RelayConfig["sendingKeys"] = interface{}([]any{address.String()}) - assert.Equal(t, "CreateJobFailed: sending keys and transmitter ID can't both be defined", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: sending keys and transmitter ID can't both be defined", jobORM.CreateJob(ctx, &jb).Error()) }) t.Run("transmitter validation works", func(t *testing.T) { + ctx := testutils.Context(t) jb.OCR2OracleSpec.TransmitterID = null.StringFrom("transmitterID that doesn't have a match in key store") jb.OCR2OracleSpec.RelayConfig["sendingKeys"] = nil - assert.Equal(t, "CreateJobFailed: no EVM key matching: \"transmitterID that doesn't have a match in key store\": no such transmitter key exists", jobORM.CreateJob(&jb).Error()) + assert.Equal(t, "CreateJobFailed: no EVM key matching: \"transmitterID that doesn't have a match in key store\": no such transmitter key exists", jobORM.CreateJob(ctx, &jb).Error()) }) } @@ -998,7 +1014,7 @@ func Test_FindJobs(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -1016,7 +1032,7 @@ func Test_FindJobs(t *testing.T) { ) require.NoError(t, err) - err = orm.CreateJob(&jb1) + err = orm.CreateJob(ctx, &jb1) require.NoError(t, err) jb2, err := directrequest.ValidatedDirectRequestSpec( @@ -1024,11 +1040,11 @@ func Test_FindJobs(t *testing.T) { ) require.NoError(t, err) - err = orm.CreateJob(&jb2) + err = orm.CreateJob(ctx, &jb2) require.NoError(t, err) t.Run("jobs are ordered by latest first", func(t *testing.T) { - jobs, count, err2 := orm.FindJobs(0, 2) + jobs, count, err2 := orm.FindJobs(testutils.Context(t), 0, 2) require.NoError(t, err2) require.Len(t, jobs, 2) assert.Equal(t, count, 2) @@ -1041,7 +1057,7 @@ func Test_FindJobs(t *testing.T) { }) t.Run("jobs respect pagination", func(t *testing.T) { - jobs, count, err2 := orm.FindJobs(0, 1) + jobs, count, err2 := orm.FindJobs(testutils.Context(t), 0, 1) require.NoError(t, err2) require.Len(t, jobs, 1) assert.Equal(t, count, 2) @@ -1080,7 +1096,7 @@ func Test_FindJob(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -1148,20 +1164,20 @@ func Test_FindJob(t *testing.T) { jobOCR2WithFeedID2.Name = null.StringFrom("new name") require.NoError(t, err) - err = orm.CreateJob(&job) + err = orm.CreateJob(ctx, &job) require.NoError(t, err) - err = orm.CreateJob(&jobSameAddress) + err = orm.CreateJob(ctx, &jobSameAddress) require.NoError(t, err) - err = orm.CreateJob(&jobOCR2) + err = orm.CreateJob(ctx, &jobOCR2) require.NoError(t, err) - err = orm.CreateJob(&jobOCR2WithFeedID1) + err = orm.CreateJob(ctx, &jobOCR2WithFeedID1) require.NoError(t, err) // second ocr2 job with same contract id but different feed id - err = orm.CreateJob(&jobOCR2WithFeedID2) + err = orm.CreateJob(ctx, &jobOCR2WithFeedID2) require.NoError(t, err) t.Run("by id", func(t *testing.T) { @@ -1180,7 +1196,8 @@ func Test_FindJob(t *testing.T) { }) t.Run("by external job id", func(t *testing.T) { - jb, err2 := orm.FindJobByExternalJobID(externalJobID) + ctx := testutils.Context(t) + jb, err2 := orm.FindJobByExternalJobID(ctx, externalJobID) require.NoError(t, err2) assert.Equal(t, jb.ID, job.ID) @@ -1193,59 +1210,64 @@ func Test_FindJob(t *testing.T) { }) t.Run("by address", func(t *testing.T) { - jbID, err2 := orm.FindJobIDByAddress(job.OCROracleSpec.ContractAddress, job.OCROracleSpec.EVMChainID) + ctx := testutils.Context(t) + jbID, err2 := orm.FindJobIDByAddress(ctx, job.OCROracleSpec.ContractAddress, job.OCROracleSpec.EVMChainID) require.NoError(t, err2) assert.Equal(t, job.ID, jbID) - _, err2 = orm.FindJobIDByAddress("not-existing", big.NewI(0)) + _, err2 = orm.FindJobIDByAddress(ctx, "not-existing", big.NewI(0)) require.Error(t, err2) require.ErrorIs(t, err2, sql.ErrNoRows) }) t.Run("by address yet chain scoped", func(t *testing.T) { + ctx := testutils.Context(t) commonAddr := jobSameAddress.OCROracleSpec.ContractAddress // Find job ID for job on chain 1337 with common address. - jbID, err2 := orm.FindJobIDByAddress(commonAddr, jobSameAddress.OCROracleSpec.EVMChainID) + jbID, err2 := orm.FindJobIDByAddress(ctx, commonAddr, jobSameAddress.OCROracleSpec.EVMChainID) require.NoError(t, err2) assert.Equal(t, jobSameAddress.ID, jbID) // Find job ID for job on default evm chain with common address. - jbID, err2 = orm.FindJobIDByAddress(commonAddr, job.OCROracleSpec.EVMChainID) + jbID, err2 = orm.FindJobIDByAddress(ctx, commonAddr, job.OCROracleSpec.EVMChainID) require.NoError(t, err2) assert.Equal(t, job.ID, jbID) }) t.Run("by contract id without feed id", func(t *testing.T) { + ctx := testutils.Context(t) contractID := "0x613a38AC1659769640aaE063C651F48E0250454C" // Find job ID for ocr2 job without feedID. - jbID, err2 := orm.FindOCR2JobIDByAddress(contractID, nil) + jbID, err2 := orm.FindOCR2JobIDByAddress(ctx, contractID, nil) require.NoError(t, err2) assert.Equal(t, jobOCR2.ID, jbID) }) t.Run("by contract id with valid feed id", func(t *testing.T) { + ctx := testutils.Context(t) contractID := "0x0000000000000000000000000000000000000006" feedID := common.HexToHash(ocr2WithFeedID1) // Find job ID for ocr2 job with feed ID - jbID, err2 := orm.FindOCR2JobIDByAddress(contractID, &feedID) + jbID, err2 := orm.FindOCR2JobIDByAddress(ctx, contractID, &feedID) require.NoError(t, err2) assert.Equal(t, jobOCR2WithFeedID1.ID, jbID) }) t.Run("with duplicate contract id but different feed id", func(t *testing.T) { + ctx := testutils.Context(t) contractID := "0x0000000000000000000000000000000000000006" feedID := common.HexToHash(ocr2WithFeedID2) // Find job ID for ocr2 job with feed ID - jbID, err2 := orm.FindOCR2JobIDByAddress(contractID, &feedID) + jbID, err2 := orm.FindOCR2JobIDByAddress(ctx, contractID, &feedID) require.NoError(t, err2) assert.Equal(t, jobOCR2WithFeedID2.ID, jbID) @@ -1263,17 +1285,18 @@ func Test_FindJobsByPipelineSpecIDs(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.GetDirectRequestSpec()) require.NoError(t, err) jb.DirectRequestSpec.EVMChainID = big.NewI(0) - err = orm.CreateJob(&jb) + err = orm.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) t.Run("with jobs", func(t *testing.T) { - jbs, err2 := orm.FindJobsByPipelineSpecIDs([]int32{jb.PipelineSpecID}) + ctx := testutils.Context(t) + jbs, err2 := orm.FindJobsByPipelineSpecIDs(ctx, []int32{jb.PipelineSpecID}) require.NoError(t, err2) assert.Len(t, jbs, 1) @@ -1286,15 +1309,17 @@ func Test_FindJobsByPipelineSpecIDs(t *testing.T) { }) t.Run("without jobs", func(t *testing.T) { - jbs, err2 := orm.FindJobsByPipelineSpecIDs([]int32{-1}) + ctx := testutils.Context(t) + jbs, err2 := orm.FindJobsByPipelineSpecIDs(ctx, []int32{-1}) require.NoError(t, err2) assert.Len(t, jbs, 0) }) t.Run("with chainID disabled", func(t *testing.T) { - orm2 := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + ctx := testutils.Context(t) + orm2 := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) - jbs, err2 := orm2.FindJobsByPipelineSpecIDs([]int32{jb.PipelineSpecID}) + jbs, err2 := orm2.FindJobsByPipelineSpecIDs(ctx, []int32{jb.PipelineSpecID}) require.NoError(t, err2) assert.Len(t, jbs, 1) }) @@ -1314,7 +1339,7 @@ func Test_FindPipelineRuns(t *testing.T) { bridgesORM := bridges.NewORM(db) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -1331,20 +1356,22 @@ func Test_FindPipelineRuns(t *testing.T) { ) require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) t.Run("with no pipeline runs", func(t *testing.T) { - runs, count, err2 := orm.PipelineRuns(nil, 0, 10) + ctx := testutils.Context(t) + runs, count, err2 := orm.PipelineRuns(ctx, nil, 0, 10) require.NoError(t, err2) assert.Equal(t, count, 0) assert.Empty(t, runs) }) t.Run("with a pipeline run", func(t *testing.T) { + ctx := testutils.Context(t) run := mustInsertPipelineRun(t, pipelineORM, jb) - runs, count, err2 := orm.PipelineRuns(nil, 0, 10) + runs, count, err2 := orm.PipelineRuns(ctx, nil, 0, 10) require.NoError(t, err2) assert.Equal(t, count, 1) @@ -1376,7 +1403,7 @@ func Test_PipelineRunsByJobID(t *testing.T) { bridgesORM := bridges.NewORM(db) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -1393,20 +1420,22 @@ func Test_PipelineRunsByJobID(t *testing.T) { ) require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) t.Run("with no pipeline runs", func(t *testing.T) { - runs, count, err2 := orm.PipelineRuns(&jb.ID, 0, 10) + ctx := testutils.Context(t) + runs, count, err2 := orm.PipelineRuns(ctx, &jb.ID, 0, 10) require.NoError(t, err2) assert.Equal(t, count, 0) assert.Empty(t, runs) }) t.Run("with a pipeline run", func(t *testing.T) { + ctx := testutils.Context(t) run := mustInsertPipelineRun(t, pipelineORM, jb) - runs, count, err2 := orm.PipelineRuns(&jb.ID, 0, 10) + runs, count, err2 := orm.PipelineRuns(ctx, &jb.ID, 0, 10) require.NoError(t, err2) assert.Equal(t, 1, count) @@ -1437,7 +1466,7 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) { bridgesORM := bridges.NewORM(db) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, address := cltest.MustInsertRandomKey(t, keyStore.Eth()) @@ -1461,7 +1490,7 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) { require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) jobs[j] = jb } @@ -1475,15 +1504,17 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) { } t.Run("with no pipeline runs", func(t *testing.T) { - runIDs, err := orm.FindPipelineRunIDsByJobID(jb.ID, 0, 10) + ctx := testutils.Context(t) + runIDs, err := orm.FindPipelineRunIDsByJobID(ctx, jb.ID, 0, 10) require.NoError(t, err) assert.Empty(t, runIDs) }) t.Run("with a pipeline run", func(t *testing.T) { + ctx := testutils.Context(t) run := mustInsertPipelineRun(t, pipelineORM, jb) - runIDs, err := orm.FindPipelineRunIDsByJobID(jb.ID, 0, 10) + runIDs, err := orm.FindPipelineRunIDsByJobID(ctx, jb.ID, 0, 10) require.NoError(t, err) require.Len(t, runIDs, 1) @@ -1493,7 +1524,8 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) { // Internally these queries are batched by 1000, this tests case requiring concatenation // of more than 1 batch t.Run("with batch concatenation limit 10", func(t *testing.T) { - runIDs, err := orm.FindPipelineRunIDsByJobID(jobs[3].ID, 95, 10) + ctx := testutils.Context(t) + runIDs, err := orm.FindPipelineRunIDsByJobID(ctx, jobs[3].ID, 95, 10) require.NoError(t, err) require.Len(t, runIDs, 10) assert.Equal(t, int64(4*(len(jobs)-1)), runIDs[3]-runIDs[7]) @@ -1502,7 +1534,8 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) { // Internally these queries are batched by 1000, this tests case requiring concatenation // of more than 1 batch t.Run("with batch concatenation limit 100", func(t *testing.T) { - runIDs, err := orm.FindPipelineRunIDsByJobID(jobs[3].ID, 95, 100) + ctx := testutils.Context(t) + runIDs, err := orm.FindPipelineRunIDsByJobID(ctx, jobs[3].ID, 95, 100) require.NoError(t, err) require.Len(t, runIDs, 100) assert.Equal(t, int64(67*(len(jobs)-1)), runIDs[12]-runIDs[79]) @@ -1516,7 +1549,8 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) { // returns empty. This can happen if the job id being requested hasn't run in a while, // but many other jobs have run since. t.Run("with first batch empty, over limit", func(t *testing.T) { - runIDs, err := orm.FindPipelineRunIDsByJobID(jobs[3].ID, 0, 25) + ctx := testutils.Context(t) + runIDs, err := orm.FindPipelineRunIDsByJobID(ctx, jobs[3].ID, 0, 25) require.NoError(t, err) require.Len(t, runIDs, 25) assert.Equal(t, int64(16*(len(jobs)-1)), runIDs[7]-runIDs[23]) @@ -1524,7 +1558,8 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) { // Same as previous, but where there are fewer matching jobs than the limit t.Run("with first batch empty, under limit", func(t *testing.T) { - runIDs, err := orm.FindPipelineRunIDsByJobID(jobs[3].ID, 143, 190) + ctx := testutils.Context(t) + runIDs, err := orm.FindPipelineRunIDsByJobID(ctx, jobs[3].ID, 143, 190) require.NoError(t, err) require.Len(t, runIDs, 107) assert.Equal(t, int64(16*(len(jobs)-1)), runIDs[7]-runIDs[23]) @@ -1546,7 +1581,7 @@ func Test_FindPipelineRunsByIDs(t *testing.T) { bridgesORM := bridges.NewORM(db) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -1563,19 +1598,21 @@ func Test_FindPipelineRunsByIDs(t *testing.T) { ) require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) t.Run("with no pipeline runs", func(t *testing.T) { - runs, err2 := orm.FindPipelineRunsByIDs([]int64{-1}) + ctx := testutils.Context(t) + runs, err2 := orm.FindPipelineRunsByIDs(ctx, []int64{-1}) require.NoError(t, err2) assert.Empty(t, runs) }) t.Run("with a pipeline run", func(t *testing.T) { + ctx := testutils.Context(t) run := mustInsertPipelineRun(t, pipelineORM, jb) - actual, err2 := orm.FindPipelineRunsByIDs([]int64{run.ID}) + actual, err2 := orm.FindPipelineRunsByIDs(ctx, []int64{run.ID}) require.NoError(t, err2) require.Len(t, actual, 1) @@ -1603,24 +1640,26 @@ func Test_FindPipelineRunByID(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.GetDirectRequestSpec()) require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) t.Run("with no pipeline run", func(t *testing.T) { - run, err2 := orm.FindPipelineRunByID(-1) + ctx := testutils.Context(t) + run, err2 := orm.FindPipelineRunByID(ctx, -1) assert.Equal(t, run, pipeline.Run{}) require.ErrorIs(t, err2, sql.ErrNoRows) }) t.Run("with a pipeline run", func(t *testing.T) { + ctx := testutils.Context(t) run := mustInsertPipelineRun(t, pipelineORM, jb) - actual, err2 := orm.FindPipelineRunByID(run.ID) + actual, err2 := orm.FindPipelineRunByID(ctx, run.ID) require.NoError(t, err2) actualRun := actual @@ -1647,12 +1686,12 @@ func Test_FindJobWithoutSpecErrors(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.GetDirectRequestSpec()) require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(ctx, &jb) require.NoError(t, err) var jobSpec job.Job err = db.Get(&jobSpec, "SELECT * FROM jobs") @@ -1660,10 +1699,10 @@ func Test_FindJobWithoutSpecErrors(t *testing.T) { ocrSpecError1 := "ocr spec 1 errored" ocrSpecError2 := "ocr spec 2 errored" - require.NoError(t, orm.RecordError(jobSpec.ID, ocrSpecError1)) - require.NoError(t, orm.RecordError(jobSpec.ID, ocrSpecError2)) + require.NoError(t, orm.RecordError(ctx, jobSpec.ID, ocrSpecError1)) + require.NoError(t, orm.RecordError(ctx, jobSpec.ID, ocrSpecError2)) - jb, err = orm.FindJobWithoutSpecErrors(jobSpec.ID) + jb, err = orm.FindJobWithoutSpecErrors(ctx, jobSpec.ID) require.NoError(t, err) jbWithErrors, err := orm.FindJobTx(testutils.Context(t), jobSpec.ID) require.NoError(t, err) @@ -1685,12 +1724,12 @@ func Test_FindSpecErrorsByJobIDs(t *testing.T) { pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.GetDirectRequestSpec()) require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(ctx, &jb) require.NoError(t, err) var jobSpec job.Job err = db.Get(&jobSpec, "SELECT * FROM jobs") @@ -1698,10 +1737,10 @@ func Test_FindSpecErrorsByJobIDs(t *testing.T) { ocrSpecError1 := "ocr spec 1 errored" ocrSpecError2 := "ocr spec 2 errored" - require.NoError(t, orm.RecordError(jobSpec.ID, ocrSpecError1)) - require.NoError(t, orm.RecordError(jobSpec.ID, ocrSpecError2)) + require.NoError(t, orm.RecordError(ctx, jobSpec.ID, ocrSpecError1)) + require.NoError(t, orm.RecordError(ctx, jobSpec.ID, ocrSpecError2)) - specErrs, err := orm.FindSpecErrorsByJobIDs([]int32{jobSpec.ID}) + specErrs, err := orm.FindSpecErrorsByJobIDs(ctx, []int32{jobSpec.ID}) require.NoError(t, err) assert.Equal(t, len(specErrs), 2) @@ -1722,7 +1761,7 @@ func Test_CountPipelineRunsByJobID(t *testing.T) { bridgesORM := bridges.NewORM(db) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) - orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore, config.Database()) + orm := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -1739,19 +1778,21 @@ func Test_CountPipelineRunsByJobID(t *testing.T) { ) require.NoError(t, err) - err = orm.CreateJob(&jb) + err = orm.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) t.Run("with no pipeline runs", func(t *testing.T) { - count, err2 := orm.CountPipelineRunsByJobID(jb.ID) + ctx := testutils.Context(t) + count, err2 := orm.CountPipelineRunsByJobID(ctx, jb.ID) require.NoError(t, err2) assert.Equal(t, int32(0), count) }) t.Run("with a pipeline run", func(t *testing.T) { + ctx := testutils.Context(t) mustInsertPipelineRun(t, pipelineORM, jb) - count, err2 := orm.CountPipelineRunsByJobID(jb.ID) + count, err2 := orm.CountPipelineRunsByJobID(ctx, jb.ID) require.NoError(t, err2) require.Equal(t, int32(1), count) }) diff --git a/core/services/job/job_pipeline_orm_integration_test.go b/core/services/job/job_pipeline_orm_integration_test.go index 33ee6dc306c..f8a43bca34d 100644 --- a/core/services/job/job_pipeline_orm_integration_test.go +++ b/core/services/job/job_pipeline_orm_integration_test.go @@ -135,7 +135,7 @@ func TestPipelineORM_Integration(t *testing.T) { p, err := pipeline.Parse(DotStr) require.NoError(t, err) - specID, err = orm.CreateSpec(ctx, nil, *p, models.Interval(0)) + specID, err = orm.CreateSpec(ctx, *p, models.Interval(0)) require.NoError(t, err) var pipelineSpecs []pipeline.Spec @@ -160,12 +160,12 @@ func TestPipelineORM_Integration(t *testing.T) { legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) runner := pipeline.NewRunner(orm, btORM, config.JobPipeline(), cfg.WebServer(), legacyChains, nil, nil, lggr, nil, nil) - jobORM := NewTestORM(t, db, orm, btORM, keyStore, cfg.Database()) + jobORM := NewTestORM(t, db, orm, btORM, keyStore) dbSpec := makeVoterTurnoutOCRJobSpec(t, transmitterAddress, bridge.Name.String(), bridge2.Name.String()) // Need a job in order to create a run - require.NoError(t, jobORM.CreateJob(dbSpec)) + require.NoError(t, jobORM.CreateJob(testutils.Context(t), dbSpec)) var pipelineSpecs []pipeline.Spec sql := `SELECT pipeline_specs.*, job_pipeline_specs.job_id FROM pipeline_specs JOIN job_pipeline_specs ON (pipeline_specs.id = job_pipeline_specs.pipeline_spec_id);` diff --git a/core/services/job/kv_orm.go b/core/services/job/kv_orm.go index 6108c123a62..63384efc25b 100644 --- a/core/services/job/kv_orm.go +++ b/core/services/job/kv_orm.go @@ -5,10 +5,8 @@ import ( "fmt" "time" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) // KVStore is a simple KV store that can store and retrieve serializable data. @@ -21,17 +19,17 @@ type KVStore interface { type kVStore struct { jobID int32 - q pg.Q + ds sqlutil.DataSource lggr logger.SugaredLogger } var _ KVStore = (*kVStore)(nil) -func NewKVStore(jobID int32, db *sqlx.DB, cfg pg.QConfig, lggr logger.Logger) kVStore { +func NewKVStore(jobID int32, ds sqlutil.DataSource, lggr logger.Logger) kVStore { namedLogger := logger.Sugared(lggr.Named("JobORM")) return kVStore{ jobID: jobID, - q: pg.NewQ(db, namedLogger, cfg), + ds: ds, lggr: namedLogger, } } @@ -45,7 +43,7 @@ func (kv kVStore) Store(ctx context.Context, key string, val []byte) error { val_bytea = EXCLUDED.val_bytea, updated_at = $4;` - if _, err := kv.q.ExecContext(ctx, sql, kv.jobID, key, val, time.Now()); err != nil { + if _, err := kv.ds.ExecContext(ctx, sql, kv.jobID, key, val, time.Now()); err != nil { return fmt.Errorf("failed to store value: %s for key: %s for jobID: %d : %w", string(val), key, kv.jobID, err) } return nil @@ -55,7 +53,7 @@ func (kv kVStore) Store(ctx context.Context, key string, val []byte) error { func (kv kVStore) Get(ctx context.Context, key string) ([]byte, error) { var val []byte sql := "SELECT val_bytea FROM job_kv_store WHERE job_id = $1 AND key = $2" - if err := kv.q.GetContext(ctx, &val, sql, kv.jobID, key); err != nil { + if err := kv.ds.GetContext(ctx, &val, sql, kv.jobID, key); err != nil { return nil, fmt.Errorf("failed to get value by key: %s for jobID: %d : %w", key, kv.jobID, err) } diff --git a/core/services/job/kv_orm_test.go b/core/services/job/kv_orm_test.go index 156779ffb4d..0f229f09d88 100644 --- a/core/services/job/kv_orm_test.go +++ b/core/services/job/kv_orm_test.go @@ -11,6 +11,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -33,13 +34,13 @@ func TestJobKVStore(t *testing.T) { bridgesORM := bridges.NewORM(db) jobID := int32(1337) - kvStore := job.NewKVStore(jobID, db, config.Database(), lggr) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, cltest.NewKeyStore(t, db), config.Database()) + kvStore := job.NewKVStore(jobID, db, lggr) + jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, cltest.NewKeyStore(t, db)) jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.GetDirectRequestSpec()) require.NoError(t, err) jb.ID = jobID - require.NoError(t, jobORM.CreateJob(&jb)) + require.NoError(t, jobORM.CreateJob(testutils.Context(t), &jb)) var values = [][]byte{ []byte("Hello"), @@ -72,5 +73,5 @@ func TestJobKVStore(t *testing.T) { require.NoError(t, err) require.Equal(t, td2, fetchedBytes) - require.NoError(t, jobORM.DeleteJob(jobID)) + require.NoError(t, jobORM.DeleteJob(ctx, jobID)) } diff --git a/core/services/job/mocks/orm.go b/core/services/job/mocks/orm.go index b8534b9d688..ec60137de93 100644 --- a/core/services/job/mocks/orm.go +++ b/core/services/job/mocks/orm.go @@ -12,10 +12,10 @@ import ( mock "github.com/stretchr/testify/mock" - pg "github.com/smartcontractkit/chainlink/v2/core/services/pg" - pipeline "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" + sqlutil "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + types "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" uuid "github.com/google/uuid" @@ -62,9 +62,9 @@ func (_m *ORM) Close() error { return r0 } -// CountPipelineRunsByJobID provides a mock function with given fields: jobID -func (_m *ORM) CountPipelineRunsByJobID(jobID int32) (int32, error) { - ret := _m.Called(jobID) +// CountPipelineRunsByJobID provides a mock function with given fields: ctx, jobID +func (_m *ORM) CountPipelineRunsByJobID(ctx context.Context, jobID int32) (int32, error) { + ret := _m.Called(ctx, jobID) if len(ret) == 0 { panic("no return value specified for CountPipelineRunsByJobID") @@ -72,17 +72,17 @@ func (_m *ORM) CountPipelineRunsByJobID(jobID int32) (int32, error) { var r0 int32 var r1 error - if rf, ok := ret.Get(0).(func(int32) (int32, error)); ok { - return rf(jobID) + if rf, ok := ret.Get(0).(func(context.Context, int32) (int32, error)); ok { + return rf(ctx, jobID) } - if rf, ok := ret.Get(0).(func(int32) int32); ok { - r0 = rf(jobID) + if rf, ok := ret.Get(0).(func(context.Context, int32) int32); ok { + r0 = rf(ctx, jobID) } else { r0 = ret.Get(0).(int32) } - if rf, ok := ret.Get(1).(func(int32) error); ok { - r1 = rf(jobID) + if rf, ok := ret.Get(1).(func(context.Context, int32) error); ok { + r1 = rf(ctx, jobID) } else { r1 = ret.Error(1) } @@ -90,24 +90,17 @@ func (_m *ORM) CountPipelineRunsByJobID(jobID int32) (int32, error) { return r0, r1 } -// CreateJob provides a mock function with given fields: jb, qopts -func (_m *ORM) CreateJob(jb *job.Job, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, jb) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// CreateJob provides a mock function with given fields: ctx, jb +func (_m *ORM) CreateJob(ctx context.Context, jb *job.Job) error { + ret := _m.Called(ctx, jb) if len(ret) == 0 { panic("no return value specified for CreateJob") } var r0 error - if rf, ok := ret.Get(0).(func(*job.Job, ...pg.QOpt) error); ok { - r0 = rf(jb, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, *job.Job) error); ok { + r0 = rf(ctx, jb) } else { r0 = ret.Error(0) } @@ -115,24 +108,37 @@ func (_m *ORM) CreateJob(jb *job.Job, qopts ...pg.QOpt) error { return r0 } -// DeleteJob provides a mock function with given fields: id, qopts -func (_m *ORM) DeleteJob(id int32, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] +// DataSource provides a mock function with given fields: +func (_m *ORM) DataSource() sqlutil.DataSource { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for DataSource") + } + + var r0 sqlutil.DataSource + if rf, ok := ret.Get(0).(func() sqlutil.DataSource); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(sqlutil.DataSource) + } } - var _ca []interface{} - _ca = append(_ca, id) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) + + return r0 +} + +// DeleteJob provides a mock function with given fields: ctx, id +func (_m *ORM) DeleteJob(ctx context.Context, id int32) error { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for DeleteJob") } var r0 error - if rf, ok := ret.Get(0).(func(int32, ...pg.QOpt) error); ok { - r0 = rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int32) error); ok { + r0 = rf(ctx, id) } else { r0 = ret.Error(0) } @@ -186,16 +192,9 @@ func (_m *ORM) FindJob(ctx context.Context, id int32) (job.Job, error) { return r0, r1 } -// FindJobByExternalJobID provides a mock function with given fields: _a0, qopts -func (_m *ORM) FindJobByExternalJobID(_a0 uuid.UUID, qopts ...pg.QOpt) (job.Job, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, _a0) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// FindJobByExternalJobID provides a mock function with given fields: ctx, _a1 +func (_m *ORM) FindJobByExternalJobID(ctx context.Context, _a1 uuid.UUID) (job.Job, error) { + ret := _m.Called(ctx, _a1) if len(ret) == 0 { panic("no return value specified for FindJobByExternalJobID") @@ -203,17 +202,17 @@ func (_m *ORM) FindJobByExternalJobID(_a0 uuid.UUID, qopts ...pg.QOpt) (job.Job, var r0 job.Job var r1 error - if rf, ok := ret.Get(0).(func(uuid.UUID, ...pg.QOpt) (job.Job, error)); ok { - return rf(_a0, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID) (job.Job, error)); ok { + return rf(ctx, _a1) } - if rf, ok := ret.Get(0).(func(uuid.UUID, ...pg.QOpt) job.Job); ok { - r0 = rf(_a0, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID) job.Job); ok { + r0 = rf(ctx, _a1) } else { r0 = ret.Get(0).(job.Job) } - if rf, ok := ret.Get(1).(func(uuid.UUID, ...pg.QOpt) error); ok { - r1 = rf(_a0, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, uuid.UUID) error); ok { + r1 = rf(ctx, _a1) } else { r1 = ret.Error(1) } @@ -221,16 +220,9 @@ func (_m *ORM) FindJobByExternalJobID(_a0 uuid.UUID, qopts ...pg.QOpt) (job.Job, return r0, r1 } -// FindJobIDByAddress provides a mock function with given fields: address, evmChainID, qopts -func (_m *ORM) FindJobIDByAddress(address types.EIP55Address, evmChainID *big.Big, qopts ...pg.QOpt) (int32, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, address, evmChainID) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// FindJobIDByAddress provides a mock function with given fields: ctx, address, evmChainID +func (_m *ORM) FindJobIDByAddress(ctx context.Context, address types.EIP55Address, evmChainID *big.Big) (int32, error) { + ret := _m.Called(ctx, address, evmChainID) if len(ret) == 0 { panic("no return value specified for FindJobIDByAddress") @@ -238,17 +230,17 @@ func (_m *ORM) FindJobIDByAddress(address types.EIP55Address, evmChainID *big.Bi var r0 int32 var r1 error - if rf, ok := ret.Get(0).(func(types.EIP55Address, *big.Big, ...pg.QOpt) (int32, error)); ok { - return rf(address, evmChainID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, types.EIP55Address, *big.Big) (int32, error)); ok { + return rf(ctx, address, evmChainID) } - if rf, ok := ret.Get(0).(func(types.EIP55Address, *big.Big, ...pg.QOpt) int32); ok { - r0 = rf(address, evmChainID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, types.EIP55Address, *big.Big) int32); ok { + r0 = rf(ctx, address, evmChainID) } else { r0 = ret.Get(0).(int32) } - if rf, ok := ret.Get(1).(func(types.EIP55Address, *big.Big, ...pg.QOpt) error); ok { - r1 = rf(address, evmChainID, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, types.EIP55Address, *big.Big) error); ok { + r1 = rf(ctx, address, evmChainID) } else { r1 = ret.Error(1) } @@ -256,9 +248,9 @@ func (_m *ORM) FindJobIDByAddress(address types.EIP55Address, evmChainID *big.Bi return r0, r1 } -// FindJobIDsWithBridge provides a mock function with given fields: name -func (_m *ORM) FindJobIDsWithBridge(name string) ([]int32, error) { - ret := _m.Called(name) +// FindJobIDsWithBridge provides a mock function with given fields: ctx, name +func (_m *ORM) FindJobIDsWithBridge(ctx context.Context, name string) ([]int32, error) { + ret := _m.Called(ctx, name) if len(ret) == 0 { panic("no return value specified for FindJobIDsWithBridge") @@ -266,19 +258,19 @@ func (_m *ORM) FindJobIDsWithBridge(name string) ([]int32, error) { var r0 []int32 var r1 error - if rf, ok := ret.Get(0).(func(string) ([]int32, error)); ok { - return rf(name) + if rf, ok := ret.Get(0).(func(context.Context, string) ([]int32, error)); ok { + return rf(ctx, name) } - if rf, ok := ret.Get(0).(func(string) []int32); ok { - r0 = rf(name) + if rf, ok := ret.Get(0).(func(context.Context, string) []int32); ok { + r0 = rf(ctx, name) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]int32) } } - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, name) } else { r1 = ret.Error(1) } @@ -314,9 +306,9 @@ func (_m *ORM) FindJobTx(ctx context.Context, id int32) (job.Job, error) { return r0, r1 } -// FindJobWithoutSpecErrors provides a mock function with given fields: id -func (_m *ORM) FindJobWithoutSpecErrors(id int32) (job.Job, error) { - ret := _m.Called(id) +// FindJobWithoutSpecErrors provides a mock function with given fields: ctx, id +func (_m *ORM) FindJobWithoutSpecErrors(ctx context.Context, id int32) (job.Job, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for FindJobWithoutSpecErrors") @@ -324,17 +316,17 @@ func (_m *ORM) FindJobWithoutSpecErrors(id int32) (job.Job, error) { var r0 job.Job var r1 error - if rf, ok := ret.Get(0).(func(int32) (job.Job, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int32) (job.Job, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int32) job.Job); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int32) job.Job); ok { + r0 = rf(ctx, id) } else { r0 = ret.Get(0).(job.Job) } - if rf, ok := ret.Get(1).(func(int32) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, int32) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -342,9 +334,9 @@ func (_m *ORM) FindJobWithoutSpecErrors(id int32) (job.Job, error) { return r0, r1 } -// FindJobs provides a mock function with given fields: offset, limit -func (_m *ORM) FindJobs(offset int, limit int) ([]job.Job, int, error) { - ret := _m.Called(offset, limit) +// FindJobs provides a mock function with given fields: ctx, offset, limit +func (_m *ORM) FindJobs(ctx context.Context, offset int, limit int) ([]job.Job, int, error) { + ret := _m.Called(ctx, offset, limit) if len(ret) == 0 { panic("no return value specified for FindJobs") @@ -353,25 +345,25 @@ func (_m *ORM) FindJobs(offset int, limit int) ([]job.Job, int, error) { var r0 []job.Job var r1 int var r2 error - if rf, ok := ret.Get(0).(func(int, int) ([]job.Job, int, error)); ok { - return rf(offset, limit) + if rf, ok := ret.Get(0).(func(context.Context, int, int) ([]job.Job, int, error)); ok { + return rf(ctx, offset, limit) } - if rf, ok := ret.Get(0).(func(int, int) []job.Job); ok { - r0 = rf(offset, limit) + if rf, ok := ret.Get(0).(func(context.Context, int, int) []job.Job); ok { + r0 = rf(ctx, offset, limit) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]job.Job) } } - if rf, ok := ret.Get(1).(func(int, int) int); ok { - r1 = rf(offset, limit) + if rf, ok := ret.Get(1).(func(context.Context, int, int) int); ok { + r1 = rf(ctx, offset, limit) } else { r1 = ret.Get(1).(int) } - if rf, ok := ret.Get(2).(func(int, int) error); ok { - r2 = rf(offset, limit) + if rf, ok := ret.Get(2).(func(context.Context, int, int) error); ok { + r2 = rf(ctx, offset, limit) } else { r2 = ret.Error(2) } @@ -379,9 +371,9 @@ func (_m *ORM) FindJobs(offset int, limit int) ([]job.Job, int, error) { return r0, r1, r2 } -// FindJobsByPipelineSpecIDs provides a mock function with given fields: ids -func (_m *ORM) FindJobsByPipelineSpecIDs(ids []int32) ([]job.Job, error) { - ret := _m.Called(ids) +// FindJobsByPipelineSpecIDs provides a mock function with given fields: ctx, ids +func (_m *ORM) FindJobsByPipelineSpecIDs(ctx context.Context, ids []int32) ([]job.Job, error) { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for FindJobsByPipelineSpecIDs") @@ -389,19 +381,19 @@ func (_m *ORM) FindJobsByPipelineSpecIDs(ids []int32) ([]job.Job, error) { var r0 []job.Job var r1 error - if rf, ok := ret.Get(0).(func([]int32) ([]job.Job, error)); ok { - return rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int32) ([]job.Job, error)); ok { + return rf(ctx, ids) } - if rf, ok := ret.Get(0).(func([]int32) []job.Job); ok { - r0 = rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int32) []job.Job); ok { + r0 = rf(ctx, ids) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]job.Job) } } - if rf, ok := ret.Get(1).(func([]int32) error); ok { - r1 = rf(ids) + if rf, ok := ret.Get(1).(func(context.Context, []int32) error); ok { + r1 = rf(ctx, ids) } else { r1 = ret.Error(1) } @@ -409,16 +401,9 @@ func (_m *ORM) FindJobsByPipelineSpecIDs(ids []int32) ([]job.Job, error) { return r0, r1 } -// FindOCR2JobIDByAddress provides a mock function with given fields: contractID, feedID, qopts -func (_m *ORM) FindOCR2JobIDByAddress(contractID string, feedID *common.Hash, qopts ...pg.QOpt) (int32, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, contractID, feedID) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// FindOCR2JobIDByAddress provides a mock function with given fields: ctx, contractID, feedID +func (_m *ORM) FindOCR2JobIDByAddress(ctx context.Context, contractID string, feedID *common.Hash) (int32, error) { + ret := _m.Called(ctx, contractID, feedID) if len(ret) == 0 { panic("no return value specified for FindOCR2JobIDByAddress") @@ -426,17 +411,17 @@ func (_m *ORM) FindOCR2JobIDByAddress(contractID string, feedID *common.Hash, qo var r0 int32 var r1 error - if rf, ok := ret.Get(0).(func(string, *common.Hash, ...pg.QOpt) (int32, error)); ok { - return rf(contractID, feedID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, string, *common.Hash) (int32, error)); ok { + return rf(ctx, contractID, feedID) } - if rf, ok := ret.Get(0).(func(string, *common.Hash, ...pg.QOpt) int32); ok { - r0 = rf(contractID, feedID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, string, *common.Hash) int32); ok { + r0 = rf(ctx, contractID, feedID) } else { r0 = ret.Get(0).(int32) } - if rf, ok := ret.Get(1).(func(string, *common.Hash, ...pg.QOpt) error); ok { - r1 = rf(contractID, feedID, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, string, *common.Hash) error); ok { + r1 = rf(ctx, contractID, feedID) } else { r1 = ret.Error(1) } @@ -444,9 +429,9 @@ func (_m *ORM) FindOCR2JobIDByAddress(contractID string, feedID *common.Hash, qo return r0, r1 } -// FindPipelineRunByID provides a mock function with given fields: id -func (_m *ORM) FindPipelineRunByID(id int64) (pipeline.Run, error) { - ret := _m.Called(id) +// FindPipelineRunByID provides a mock function with given fields: ctx, id +func (_m *ORM) FindPipelineRunByID(ctx context.Context, id int64) (pipeline.Run, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for FindPipelineRunByID") @@ -454,17 +439,17 @@ func (_m *ORM) FindPipelineRunByID(id int64) (pipeline.Run, error) { var r0 pipeline.Run var r1 error - if rf, ok := ret.Get(0).(func(int64) (pipeline.Run, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) (pipeline.Run, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64) pipeline.Run); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, int64) pipeline.Run); ok { + r0 = rf(ctx, id) } else { r0 = ret.Get(0).(pipeline.Run) } - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -472,9 +457,9 @@ func (_m *ORM) FindPipelineRunByID(id int64) (pipeline.Run, error) { return r0, r1 } -// FindPipelineRunIDsByJobID provides a mock function with given fields: jobID, offset, limit -func (_m *ORM) FindPipelineRunIDsByJobID(jobID int32, offset int, limit int) ([]int64, error) { - ret := _m.Called(jobID, offset, limit) +// FindPipelineRunIDsByJobID provides a mock function with given fields: ctx, jobID, offset, limit +func (_m *ORM) FindPipelineRunIDsByJobID(ctx context.Context, jobID int32, offset int, limit int) ([]int64, error) { + ret := _m.Called(ctx, jobID, offset, limit) if len(ret) == 0 { panic("no return value specified for FindPipelineRunIDsByJobID") @@ -482,19 +467,19 @@ func (_m *ORM) FindPipelineRunIDsByJobID(jobID int32, offset int, limit int) ([] var r0 []int64 var r1 error - if rf, ok := ret.Get(0).(func(int32, int, int) ([]int64, error)); ok { - return rf(jobID, offset, limit) + if rf, ok := ret.Get(0).(func(context.Context, int32, int, int) ([]int64, error)); ok { + return rf(ctx, jobID, offset, limit) } - if rf, ok := ret.Get(0).(func(int32, int, int) []int64); ok { - r0 = rf(jobID, offset, limit) + if rf, ok := ret.Get(0).(func(context.Context, int32, int, int) []int64); ok { + r0 = rf(ctx, jobID, offset, limit) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]int64) } } - if rf, ok := ret.Get(1).(func(int32, int, int) error); ok { - r1 = rf(jobID, offset, limit) + if rf, ok := ret.Get(1).(func(context.Context, int32, int, int) error); ok { + r1 = rf(ctx, jobID, offset, limit) } else { r1 = ret.Error(1) } @@ -502,9 +487,9 @@ func (_m *ORM) FindPipelineRunIDsByJobID(jobID int32, offset int, limit int) ([] return r0, r1 } -// FindPipelineRunsByIDs provides a mock function with given fields: ids -func (_m *ORM) FindPipelineRunsByIDs(ids []int64) ([]pipeline.Run, error) { - ret := _m.Called(ids) +// FindPipelineRunsByIDs provides a mock function with given fields: ctx, ids +func (_m *ORM) FindPipelineRunsByIDs(ctx context.Context, ids []int64) ([]pipeline.Run, error) { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for FindPipelineRunsByIDs") @@ -512,19 +497,19 @@ func (_m *ORM) FindPipelineRunsByIDs(ids []int64) ([]pipeline.Run, error) { var r0 []pipeline.Run var r1 error - if rf, ok := ret.Get(0).(func([]int64) ([]pipeline.Run, error)); ok { - return rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) ([]pipeline.Run, error)); ok { + return rf(ctx, ids) } - if rf, ok := ret.Get(0).(func([]int64) []pipeline.Run); ok { - r0 = rf(ids) + if rf, ok := ret.Get(0).(func(context.Context, []int64) []pipeline.Run); ok { + r0 = rf(ctx, ids) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]pipeline.Run) } } - if rf, ok := ret.Get(1).(func([]int64) error); ok { - r1 = rf(ids) + if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok { + r1 = rf(ctx, ids) } else { r1 = ret.Error(1) } @@ -532,16 +517,9 @@ func (_m *ORM) FindPipelineRunsByIDs(ids []int64) ([]pipeline.Run, error) { return r0, r1 } -// FindSpecError provides a mock function with given fields: id, qopts -func (_m *ORM) FindSpecError(id int64, qopts ...pg.QOpt) (job.SpecError, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, id) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// FindSpecError provides a mock function with given fields: ctx, id +func (_m *ORM) FindSpecError(ctx context.Context, id int64) (job.SpecError, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for FindSpecError") @@ -549,17 +527,17 @@ func (_m *ORM) FindSpecError(id int64, qopts ...pg.QOpt) (job.SpecError, error) var r0 job.SpecError var r1 error - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) (job.SpecError, error)); ok { - return rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) (job.SpecError, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(int64, ...pg.QOpt) job.SpecError); ok { - r0 = rf(id, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64) job.SpecError); ok { + r0 = rf(ctx, id) } else { r0 = ret.Get(0).(job.SpecError) } - if rf, ok := ret.Get(1).(func(int64, ...pg.QOpt) error); ok { - r1 = rf(id, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -567,16 +545,9 @@ func (_m *ORM) FindSpecError(id int64, qopts ...pg.QOpt) (job.SpecError, error) return r0, r1 } -// FindSpecErrorsByJobIDs provides a mock function with given fields: ids, qopts -func (_m *ORM) FindSpecErrorsByJobIDs(ids []int32, qopts ...pg.QOpt) ([]job.SpecError, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, ids) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// FindSpecErrorsByJobIDs provides a mock function with given fields: ctx, ids +func (_m *ORM) FindSpecErrorsByJobIDs(ctx context.Context, ids []int32) ([]job.SpecError, error) { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for FindSpecErrorsByJobIDs") @@ -584,19 +555,19 @@ func (_m *ORM) FindSpecErrorsByJobIDs(ids []int32, qopts ...pg.QOpt) ([]job.Spec var r0 []job.SpecError var r1 error - if rf, ok := ret.Get(0).(func([]int32, ...pg.QOpt) ([]job.SpecError, error)); ok { - return rf(ids, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, []int32) ([]job.SpecError, error)); ok { + return rf(ctx, ids) } - if rf, ok := ret.Get(0).(func([]int32, ...pg.QOpt) []job.SpecError); ok { - r0 = rf(ids, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, []int32) []job.SpecError); ok { + r0 = rf(ctx, ids) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]job.SpecError) } } - if rf, ok := ret.Get(1).(func([]int32, ...pg.QOpt) error); ok { - r1 = rf(ids, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, []int32) error); ok { + r1 = rf(ctx, ids) } else { r1 = ret.Error(1) } @@ -604,16 +575,9 @@ func (_m *ORM) FindSpecErrorsByJobIDs(ids []int32, qopts ...pg.QOpt) ([]job.Spec return r0, r1 } -// FindTaskResultByRunIDAndTaskName provides a mock function with given fields: runID, taskName, qopts -func (_m *ORM) FindTaskResultByRunIDAndTaskName(runID int64, taskName string, qopts ...pg.QOpt) ([]byte, error) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, runID, taskName) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// FindTaskResultByRunIDAndTaskName provides a mock function with given fields: ctx, runID, taskName +func (_m *ORM) FindTaskResultByRunIDAndTaskName(ctx context.Context, runID int64, taskName string) ([]byte, error) { + ret := _m.Called(ctx, runID, taskName) if len(ret) == 0 { panic("no return value specified for FindTaskResultByRunIDAndTaskName") @@ -621,19 +585,19 @@ func (_m *ORM) FindTaskResultByRunIDAndTaskName(runID int64, taskName string, qo var r0 []byte var r1 error - if rf, ok := ret.Get(0).(func(int64, string, ...pg.QOpt) ([]byte, error)); ok { - return rf(runID, taskName, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64, string) ([]byte, error)); ok { + return rf(ctx, runID, taskName) } - if rf, ok := ret.Get(0).(func(int64, string, ...pg.QOpt) []byte); ok { - r0 = rf(runID, taskName, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int64, string) []byte); ok { + r0 = rf(ctx, runID, taskName) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]byte) } } - if rf, ok := ret.Get(1).(func(int64, string, ...pg.QOpt) error); ok { - r1 = rf(runID, taskName, qopts...) + if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok { + r1 = rf(ctx, runID, taskName) } else { r1 = ret.Error(1) } @@ -641,24 +605,17 @@ func (_m *ORM) FindTaskResultByRunIDAndTaskName(runID int64, taskName string, qo return r0, r1 } -// InsertJob provides a mock function with given fields: _a0, qopts -func (_m *ORM) InsertJob(_a0 *job.Job, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, _a0) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// InsertJob provides a mock function with given fields: ctx, _a1 +func (_m *ORM) InsertJob(ctx context.Context, _a1 *job.Job) error { + ret := _m.Called(ctx, _a1) if len(ret) == 0 { panic("no return value specified for InsertJob") } var r0 error - if rf, ok := ret.Get(0).(func(*job.Job, ...pg.QOpt) error); ok { - r0 = rf(_a0, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, *job.Job) error); ok { + r0 = rf(ctx, _a1) } else { r0 = ret.Error(0) } @@ -666,24 +623,17 @@ func (_m *ORM) InsertJob(_a0 *job.Job, qopts ...pg.QOpt) error { return r0 } -// InsertWebhookSpec provides a mock function with given fields: webhookSpec, qopts -func (_m *ORM) InsertWebhookSpec(webhookSpec *job.WebhookSpec, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, webhookSpec) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// InsertWebhookSpec provides a mock function with given fields: ctx, webhookSpec +func (_m *ORM) InsertWebhookSpec(ctx context.Context, webhookSpec *job.WebhookSpec) error { + ret := _m.Called(ctx, webhookSpec) if len(ret) == 0 { panic("no return value specified for InsertWebhookSpec") } var r0 error - if rf, ok := ret.Get(0).(func(*job.WebhookSpec, ...pg.QOpt) error); ok { - r0 = rf(webhookSpec, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, *job.WebhookSpec) error); ok { + r0 = rf(ctx, webhookSpec) } else { r0 = ret.Error(0) } @@ -691,9 +641,9 @@ func (_m *ORM) InsertWebhookSpec(webhookSpec *job.WebhookSpec, qopts ...pg.QOpt) return r0 } -// PipelineRuns provides a mock function with given fields: jobID, offset, size -func (_m *ORM) PipelineRuns(jobID *int32, offset int, size int) ([]pipeline.Run, int, error) { - ret := _m.Called(jobID, offset, size) +// PipelineRuns provides a mock function with given fields: ctx, jobID, offset, size +func (_m *ORM) PipelineRuns(ctx context.Context, jobID *int32, offset int, size int) ([]pipeline.Run, int, error) { + ret := _m.Called(ctx, jobID, offset, size) if len(ret) == 0 { panic("no return value specified for PipelineRuns") @@ -702,25 +652,25 @@ func (_m *ORM) PipelineRuns(jobID *int32, offset int, size int) ([]pipeline.Run, var r0 []pipeline.Run var r1 int var r2 error - if rf, ok := ret.Get(0).(func(*int32, int, int) ([]pipeline.Run, int, error)); ok { - return rf(jobID, offset, size) + if rf, ok := ret.Get(0).(func(context.Context, *int32, int, int) ([]pipeline.Run, int, error)); ok { + return rf(ctx, jobID, offset, size) } - if rf, ok := ret.Get(0).(func(*int32, int, int) []pipeline.Run); ok { - r0 = rf(jobID, offset, size) + if rf, ok := ret.Get(0).(func(context.Context, *int32, int, int) []pipeline.Run); ok { + r0 = rf(ctx, jobID, offset, size) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]pipeline.Run) } } - if rf, ok := ret.Get(1).(func(*int32, int, int) int); ok { - r1 = rf(jobID, offset, size) + if rf, ok := ret.Get(1).(func(context.Context, *int32, int, int) int); ok { + r1 = rf(ctx, jobID, offset, size) } else { r1 = ret.Get(1).(int) } - if rf, ok := ret.Get(2).(func(*int32, int, int) error); ok { - r2 = rf(jobID, offset, size) + if rf, ok := ret.Get(2).(func(context.Context, *int32, int, int) error); ok { + r2 = rf(ctx, jobID, offset, size) } else { r2 = ret.Error(2) } @@ -728,24 +678,17 @@ func (_m *ORM) PipelineRuns(jobID *int32, offset int, size int) ([]pipeline.Run, return r0, r1, r2 } -// RecordError provides a mock function with given fields: jobID, description, qopts -func (_m *ORM) RecordError(jobID int32, description string, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, jobID, description) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// RecordError provides a mock function with given fields: ctx, jobID, description +func (_m *ORM) RecordError(ctx context.Context, jobID int32, description string) error { + ret := _m.Called(ctx, jobID, description) if len(ret) == 0 { panic("no return value specified for RecordError") } var r0 error - if rf, ok := ret.Get(0).(func(int32, string, ...pg.QOpt) error); ok { - r0 = rf(jobID, description, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, int32, string) error); ok { + r0 = rf(ctx, jobID, description) } else { r0 = ret.Error(0) } @@ -753,16 +696,29 @@ func (_m *ORM) RecordError(jobID int32, description string, qopts ...pg.QOpt) er return r0 } -// TryRecordError provides a mock function with given fields: jobID, description, qopts -func (_m *ORM) TryRecordError(jobID int32, description string, qopts ...pg.QOpt) { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] +// TryRecordError provides a mock function with given fields: ctx, jobID, description +func (_m *ORM) TryRecordError(ctx context.Context, jobID int32, description string) { + _m.Called(ctx, jobID, description) +} + +// WithDataSource provides a mock function with given fields: source +func (_m *ORM) WithDataSource(source sqlutil.DataSource) job.ORM { + ret := _m.Called(source) + + if len(ret) == 0 { + panic("no return value specified for WithDataSource") } - var _ca []interface{} - _ca = append(_ca, jobID, description) - _ca = append(_ca, _va...) - _m.Called(_ca...) + + var r0 job.ORM + if rf, ok := ret.Get(0).(func(sqlutil.DataSource) job.ORM); ok { + r0 = rf(source) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(job.ORM) + } + } + + return r0 } // NewORM creates a new instance of ORM. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. diff --git a/core/services/job/mocks/spawner.go b/core/services/job/mocks/spawner.go index 37e883ef3c5..7127636cdbb 100644 --- a/core/services/job/mocks/spawner.go +++ b/core/services/job/mocks/spawner.go @@ -8,7 +8,7 @@ import ( job "github.com/smartcontractkit/chainlink/v2/core/services/job" mock "github.com/stretchr/testify/mock" - pg "github.com/smartcontractkit/chainlink/v2/core/services/pg" + sqlutil "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" ) // Spawner is an autogenerated mock type for the Spawner type @@ -54,24 +54,17 @@ func (_m *Spawner) Close() error { return r0 } -// CreateJob provides a mock function with given fields: jb, qopts -func (_m *Spawner) CreateJob(jb *job.Job, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, jb) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// CreateJob provides a mock function with given fields: ctx, ds, jb +func (_m *Spawner) CreateJob(ctx context.Context, ds sqlutil.DataSource, jb *job.Job) error { + ret := _m.Called(ctx, ds, jb) if len(ret) == 0 { panic("no return value specified for CreateJob") } var r0 error - if rf, ok := ret.Get(0).(func(*job.Job, ...pg.QOpt) error); ok { - r0 = rf(jb, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, sqlutil.DataSource, *job.Job) error); ok { + r0 = rf(ctx, ds, jb) } else { r0 = ret.Error(0) } @@ -79,24 +72,17 @@ func (_m *Spawner) CreateJob(jb *job.Job, qopts ...pg.QOpt) error { return r0 } -// DeleteJob provides a mock function with given fields: jobID, qopts -func (_m *Spawner) DeleteJob(jobID int32, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, jobID) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// DeleteJob provides a mock function with given fields: ctx, ds, jobID +func (_m *Spawner) DeleteJob(ctx context.Context, ds sqlutil.DataSource, jobID int32) error { + ret := _m.Called(ctx, ds, jobID) if len(ret) == 0 { panic("no return value specified for DeleteJob") } var r0 error - if rf, ok := ret.Get(0).(func(int32, ...pg.QOpt) error); ok { - r0 = rf(jobID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, sqlutil.DataSource, int32) error); ok { + r0 = rf(ctx, ds, jobID) } else { r0 = ret.Error(0) } @@ -178,24 +164,17 @@ func (_m *Spawner) Start(_a0 context.Context) error { return r0 } -// StartService provides a mock function with given fields: ctx, spec, qopts -func (_m *Spawner) StartService(ctx context.Context, spec job.Job, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, spec) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// StartService provides a mock function with given fields: ctx, spec +func (_m *Spawner) StartService(ctx context.Context, spec job.Job) error { + ret := _m.Called(ctx, spec) if len(ret) == 0 { panic("no return value specified for StartService") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, job.Job, ...pg.QOpt) error); ok { - r0 = rf(ctx, spec, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, job.Job) error); ok { + r0 = rf(ctx, spec) } else { r0 = ret.Error(0) } diff --git a/core/services/job/orm.go b/core/services/job/orm.go index f7238799634..2b2f73396dc 100644 --- a/core/services/job/orm.go +++ b/core/services/job/orm.go @@ -18,6 +18,7 @@ import ( "github.com/jmoiron/sqlx" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/bridges" @@ -29,7 +30,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" medianconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/median/config" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/store/models" ) @@ -44,37 +44,40 @@ var ( //go:generate mockery --quiet --name ORM --output ./mocks/ --case=underscore type ORM interface { - InsertWebhookSpec(webhookSpec *WebhookSpec, qopts ...pg.QOpt) error - InsertJob(job *Job, qopts ...pg.QOpt) error - CreateJob(jb *Job, qopts ...pg.QOpt) error - FindJobs(offset, limit int) ([]Job, int, error) + InsertWebhookSpec(ctx context.Context, webhookSpec *WebhookSpec) error + InsertJob(ctx context.Context, job *Job) error + CreateJob(ctx context.Context, jb *Job) error + FindJobs(ctx context.Context, offset, limit int) ([]Job, int, error) FindJobTx(ctx context.Context, id int32) (Job, error) FindJob(ctx context.Context, id int32) (Job, error) - FindJobByExternalJobID(uuid uuid.UUID, qopts ...pg.QOpt) (Job, error) - FindJobIDByAddress(address evmtypes.EIP55Address, evmChainID *big.Big, qopts ...pg.QOpt) (int32, error) - FindOCR2JobIDByAddress(contractID string, feedID *common.Hash, qopts ...pg.QOpt) (int32, error) - FindJobIDsWithBridge(name string) ([]int32, error) - DeleteJob(id int32, qopts ...pg.QOpt) error - RecordError(jobID int32, description string, qopts ...pg.QOpt) error + FindJobByExternalJobID(ctx context.Context, uuid uuid.UUID) (Job, error) + FindJobIDByAddress(ctx context.Context, address evmtypes.EIP55Address, evmChainID *big.Big) (int32, error) + FindOCR2JobIDByAddress(ctx context.Context, contractID string, feedID *common.Hash) (int32, error) + FindJobIDsWithBridge(ctx context.Context, name string) ([]int32, error) + DeleteJob(ctx context.Context, id int32) error + RecordError(ctx context.Context, jobID int32, description string) error // TryRecordError is a helper which calls RecordError and logs the returned error if present. - TryRecordError(jobID int32, description string, qopts ...pg.QOpt) + TryRecordError(ctx context.Context, jobID int32, description string) DismissError(ctx context.Context, errorID int64) error - FindSpecError(id int64, qopts ...pg.QOpt) (SpecError, error) + FindSpecError(ctx context.Context, id int64) (SpecError, error) Close() error - PipelineRuns(jobID *int32, offset, size int) ([]pipeline.Run, int, error) + PipelineRuns(ctx context.Context, jobID *int32, offset, size int) ([]pipeline.Run, int, error) - FindPipelineRunIDsByJobID(jobID int32, offset, limit int) (ids []int64, err error) - FindPipelineRunsByIDs(ids []int64) (runs []pipeline.Run, err error) - CountPipelineRunsByJobID(jobID int32) (count int32, err error) + FindPipelineRunIDsByJobID(ctx context.Context, jobID int32, offset, limit int) (ids []int64, err error) + FindPipelineRunsByIDs(ctx context.Context, ids []int64) (runs []pipeline.Run, err error) + CountPipelineRunsByJobID(ctx context.Context, jobID int32) (count int32, err error) - FindJobsByPipelineSpecIDs(ids []int32) ([]Job, error) - FindPipelineRunByID(id int64) (pipeline.Run, error) + FindJobsByPipelineSpecIDs(ctx context.Context, ids []int32) ([]Job, error) + FindPipelineRunByID(ctx context.Context, id int64) (pipeline.Run, error) - FindSpecErrorsByJobIDs(ids []int32, qopts ...pg.QOpt) ([]SpecError, error) - FindJobWithoutSpecErrors(id int32) (jb Job, err error) + FindSpecErrorsByJobIDs(ctx context.Context, ids []int32) ([]SpecError, error) + FindJobWithoutSpecErrors(ctx context.Context, id int32) (jb Job, err error) - FindTaskResultByRunIDAndTaskName(runID int64, taskName string, qopts ...pg.QOpt) ([]byte, error) + FindTaskResultByRunIDAndTaskName(ctx context.Context, runID int64, taskName string) ([]byte, error) AssertBridgesExist(ctx context.Context, p pipeline.Pipeline) error + + DataSource() sqlutil.DataSource + WithDataSource(source sqlutil.DataSource) ORM } type ORMConfig interface { @@ -82,31 +85,56 @@ type ORMConfig interface { } type orm struct { - q pg.Q + ds sqlutil.DataSource keyStore keystore.Master pipelineORM pipeline.ORM lggr logger.SugaredLogger - cfg pg.QConfig bridgeORM bridges.ORM } var _ ORM = (*orm)(nil) -func NewORM(db *sqlx.DB, pipelineORM pipeline.ORM, bridgeORM bridges.ORM, keyStore keystore.Master, lggr logger.Logger, cfg pg.QConfig) *orm { +func NewORM(ds sqlutil.DataSource, pipelineORM pipeline.ORM, bridgeORM bridges.ORM, keyStore keystore.Master, lggr logger.Logger) *orm { namedLogger := logger.Sugared(lggr.Named("JobORM")) return &orm{ - q: pg.NewQ(db, namedLogger, cfg), + ds: ds, keyStore: keyStore, pipelineORM: pipelineORM, bridgeORM: bridgeORM, lggr: namedLogger, - cfg: cfg, } } + func (o *orm) Close() error { return nil } +func (o *orm) DataSource() sqlutil.DataSource { + return o.ds +} + +func (o *orm) WithDataSource(ds sqlutil.DataSource) ORM { return o.withDataSource(ds) } + +func (o *orm) withDataSource(ds sqlutil.DataSource) *orm { + n := &orm{ + ds: ds, + lggr: o.lggr, + keyStore: o.keyStore, + } + if o.bridgeORM != nil { + n.bridgeORM = o.bridgeORM.WithDataSource(ds) + } + if o.pipelineORM != nil { + n.pipelineORM = o.pipelineORM.WithDataSource(ds) + } + return n +} + +func (o *orm) transact(ctx context.Context, readOnly bool, fn func(*orm) error) error { + opts := &sqlutil.TxOptions{TxOptions: sql.TxOptions{ReadOnly: readOnly}} + return sqlutil.Transact(ctx, o.withDataSource, o.ds, opts, fn) +} + func (o *orm) AssertBridgesExist(ctx context.Context, p pipeline.Pipeline) error { var bridgeNames = make(map[bridges.BridgeName]struct{}) var uniqueBridges []bridges.BridgeName @@ -137,16 +165,14 @@ func (o *orm) AssertBridgesExist(ctx context.Context, p pipeline.Pipeline) error // CreateJob creates the job, and it's associated spec record. // Expects an unmarshalled job spec as the jb argument i.e. output from ValidatedXX. // Scans all persisted records back into jb -func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { - q := o.q.WithOpts(qopts...) +func (o *orm) CreateJob(ctx context.Context, jb *Job) error { p := jb.Pipeline - ctx := context.TODO() // TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 if err := o.AssertBridgesExist(ctx, p); err != nil { return err } var jobID int32 - err := q.Transaction(func(tx pg.Queryer) error { + err := o.transact(ctx, false, func(tx *orm) error { // Autogenerate a job ID if not specified if jb.ExternalJobID == (uuid.UUID{}) { jb.ExternalJobID = uuid.New() @@ -157,26 +183,18 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { if jb.DirectRequestSpec.EVMChainID == nil { return errors.New("evm chain id must be defined") } - var specID int32 - sql := `INSERT INTO direct_request_specs (contract_address, min_incoming_confirmations, requesters, min_contract_payment, evm_chain_id, created_at, updated_at) - VALUES (:contract_address, :min_incoming_confirmations, :requesters, :min_contract_payment, :evm_chain_id, now(), now()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, jb.DirectRequestSpec); err != nil { - return errors.Wrap(err, "failed to create DirectRequestSpec") + specID, err := tx.insertDirectRequestSpec(ctx, jb.DirectRequestSpec) + if err != nil { + return fmt.Errorf("failed to create DirectRequestSpec for jobSpec: %w", err) } jb.DirectRequestSpecID = &specID case FluxMonitor: if jb.FluxMonitorSpec.EVMChainID == nil { return errors.New("evm chain id must be defined") } - var specID int32 - sql := `INSERT INTO flux_monitor_specs (contract_address, threshold, absolute_threshold, poll_timer_period, poll_timer_disabled, idle_timer_period, idle_timer_disabled, - drumbeat_schedule, drumbeat_random_delay, drumbeat_enabled, min_payment, evm_chain_id, created_at, updated_at) - VALUES (:contract_address, :threshold, :absolute_threshold, :poll_timer_period, :poll_timer_disabled, :idle_timer_period, :idle_timer_disabled, - :drumbeat_schedule, :drumbeat_random_delay, :drumbeat_enabled, :min_payment, :evm_chain_id, NOW(), NOW()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, jb.FluxMonitorSpec); err != nil { - return errors.Wrap(err, "failed to create FluxMonitorSpec") + specID, err := tx.insertFluxMonitorSpec(ctx, jb.FluxMonitorSpec) + if err != nil { + return fmt.Errorf("failed to create FluxMonitorSpec for jobSpec: %w", err) } jb.FluxMonitorSpecID = &specID case OffchainReporting: @@ -184,15 +202,14 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { return errors.New("evm chain id must be defined") } - var specID int32 if jb.OCROracleSpec.EncryptedOCRKeyBundleID != nil { - _, err := o.keyStore.OCR().Get(jb.OCROracleSpec.EncryptedOCRKeyBundleID.String()) + _, err := tx.keyStore.OCR().Get(jb.OCROracleSpec.EncryptedOCRKeyBundleID.String()) if err != nil { return errors.Wrapf(ErrNoSuchKeyBundle, "no key bundle with id: %x", jb.OCROracleSpec.EncryptedOCRKeyBundleID) } } if jb.OCROracleSpec.TransmitterAddress != nil { - _, err := o.keyStore.Eth().Get(q.ParentCtx, jb.OCROracleSpec.TransmitterAddress.Hex()) + _, err := tx.keyStore.Eth().Get(ctx, jb.OCROracleSpec.TransmitterAddress.Hex()) if err != nil { return errors.Wrapf(ErrNoSuchTransmitterKey, "no key matching transmitter address: %s", jb.OCROracleSpec.TransmitterAddress.Hex()) } @@ -200,7 +217,7 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { newChainID := jb.OCROracleSpec.EVMChainID existingSpec := new(OCROracleSpec) - err := tx.Get(existingSpec, `SELECT * FROM ocr_oracle_specs WHERE contract_address = $1 and (evm_chain_id = $2 or evm_chain_id IS NULL) LIMIT 1;`, + err := tx.ds.GetContext(ctx, existingSpec, `SELECT * FROM ocr_oracle_specs WHERE contract_address = $1 and (evm_chain_id = $2 or evm_chain_id IS NULL) LIMIT 1;`, jb.OCROracleSpec.ContractAddress, newChainID, ) @@ -212,23 +229,14 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { return errors.Errorf("a job with contract address %s already exists for chain ID %s", jb.OCROracleSpec.ContractAddress, newChainID) } - sql := `INSERT INTO ocr_oracle_specs (contract_address, p2pv2_bootstrappers, is_bootstrap_peer, encrypted_ocr_key_bundle_id, transmitter_address, - observation_timeout, blockchain_timeout, contract_config_tracker_subscribe_interval, contract_config_tracker_poll_interval, contract_config_confirmations, evm_chain_id, - created_at, updated_at, database_timeout, observation_grace_period, contract_transmitter_transmit_timeout) - VALUES (:contract_address, :p2pv2_bootstrappers, :is_bootstrap_peer, :encrypted_ocr_key_bundle_id, :transmitter_address, - :observation_timeout, :blockchain_timeout, :contract_config_tracker_subscribe_interval, :contract_config_tracker_poll_interval, :contract_config_confirmations, :evm_chain_id, - NOW(), NOW(), :database_timeout, :observation_grace_period, :contract_transmitter_transmit_timeout) - RETURNING id;` - err = pg.PrepareQueryRowx(tx, sql, &specID, jb.OCROracleSpec) + specID, err := tx.insertOCROracleSpec(ctx, jb.OCROracleSpec) if err != nil { - return errors.Wrap(err, "failed to create OffchainreportingOracleSpec") + return fmt.Errorf("failed to create OCROracleSpec for jobSpec: %w", err) } jb.OCROracleSpecID = &specID case OffchainReporting2: - var specID int32 - if jb.OCR2OracleSpec.OCRKeyBundleID.Valid { - _, err := o.keyStore.OCR2().Get(jb.OCR2OracleSpec.OCRKeyBundleID.String) + _, err := tx.keyStore.OCR2().Get(jb.OCR2OracleSpec.OCRKeyBundleID.String) if err != nil { return errors.Wrapf(ErrNoSuchKeyBundle, "no key bundle with id: %q", jb.OCR2OracleSpec.OCRKeyBundleID.ValueOrZero()) } @@ -239,7 +247,7 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { } // checks if they are present and if they are valid - sendingKeysDefined, err := areSendingKeysDefined(q.ParentCtx, jb, o.keyStore) + sendingKeysDefined, err := areSendingKeysDefined(ctx, jb, tx.keyStore) if err != nil { return err } @@ -249,7 +257,7 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { } if !sendingKeysDefined { - if err = ValidateKeyStoreMatch(q.ParentCtx, jb.OCR2OracleSpec, o.keyStore, jb.OCR2OracleSpec.TransmitterID.String); err != nil { + if err = ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, tx.keyStore, jb.OCR2OracleSpec.TransmitterID.String); err != nil { return errors.Wrap(ErrNoSuchTransmitterKey, err.Error()) } } @@ -278,66 +286,36 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { if err2 != nil { return err2 } - if err2 = o.AssertBridgesExist(ctx, *feePipeline); err2 != nil { + if err2 = tx.AssertBridgesExist(ctx, *feePipeline); err2 != nil { return err2 } } - sql := `INSERT INTO ocr2_oracle_specs (contract_id, feed_id, relay, relay_config, plugin_type, plugin_config, p2pv2_bootstrappers, ocr_key_bundle_id, transmitter_id, - blockchain_timeout, contract_config_tracker_poll_interval, contract_config_confirmations, - created_at, updated_at) - VALUES (:contract_id, :feed_id, :relay, :relay_config, :plugin_type, :plugin_config, :p2pv2_bootstrappers, :ocr_key_bundle_id, :transmitter_id, - :blockchain_timeout, :contract_config_tracker_poll_interval, :contract_config_confirmations, - NOW(), NOW()) - RETURNING id;` - err = pg.PrepareQueryRowx(tx, sql, &specID, jb.OCR2OracleSpec) + specID, err := tx.insertOCR2OracleSpec(ctx, jb.OCR2OracleSpec) if err != nil { - return errors.Wrap(err, "failed to create Offchainreporting2OracleSpec") + return fmt.Errorf("failed to create OCR2OracleSpec for jobSpec: %w", err) } jb.OCR2OracleSpecID = &specID case Keeper: if jb.KeeperSpec.EVMChainID == nil { return errors.New("evm chain id must be defined") } - var specID int32 - sql := `INSERT INTO keeper_specs (contract_address, from_address, evm_chain_id, created_at, updated_at) - VALUES (:contract_address, :from_address, :evm_chain_id, NOW(), NOW()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, jb.KeeperSpec); err != nil { - return errors.Wrap(err, "failed to create KeeperSpec") + specID, err := tx.insertKeeperSpec(ctx, jb.KeeperSpec) + if err != nil { + return fmt.Errorf("failed to create KeeperSpec for jobSpec: %w", err) } jb.KeeperSpecID = &specID case Cron: - var specID int32 - sql := `INSERT INTO cron_specs (cron_schedule, created_at, updated_at) - VALUES (:cron_schedule, NOW(), NOW()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, jb.CronSpec); err != nil { - return errors.Wrap(err, "failed to create CronSpec") + specID, err := tx.insertCronSpec(ctx, jb.CronSpec) + if err != nil { + return fmt.Errorf("failed to create CronSpec for jobSpec: %w", err) } jb.CronSpecID = &specID case VRF: if jb.VRFSpec.EVMChainID == nil { return errors.New("evm chain id must be defined") } - var specID int32 - sql := `INSERT INTO vrf_specs ( - coordinator_address, public_key, min_incoming_confirmations, - evm_chain_id, from_addresses, poll_period, requested_confs_delay, - request_timeout, chunk_size, batch_coordinator_address, batch_fulfillment_enabled, - batch_fulfillment_gas_multiplier, backoff_initial_delay, backoff_max_delay, gas_lane_price, - vrf_owner_address, custom_reverts_pipeline_enabled, - created_at, updated_at) - VALUES ( - :coordinator_address, :public_key, :min_incoming_confirmations, - :evm_chain_id, :from_addresses, :poll_period, :requested_confs_delay, - :request_timeout, :chunk_size, :batch_coordinator_address, :batch_fulfillment_enabled, - :batch_fulfillment_gas_multiplier, :backoff_initial_delay, :backoff_max_delay, :gas_lane_price, - :vrf_owner_address, :custom_reverts_pipeline_enabled, - NOW(), NOW()) - RETURNING id;` - - err := pg.PrepareQueryRowx(tx, sql, &specID, toVRFSpecRow(jb.VRFSpec)) + specID, err := tx.insertVRFSpec(ctx, jb.VRFSpec) var pqErr *pgconn.PgError ok := errors.As(err, &pqErr) if err != nil && ok && pqErr.Code == "23503" { @@ -346,11 +324,11 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { } } if err != nil { - return errors.Wrap(err, "failed to create VRFSpec") + return fmt.Errorf("failed to create VRFSpec for jobSpec: %w", err) } jb.VRFSpecID = &specID case Webhook: - err := o.InsertWebhookSpec(jb.WebhookSpec, pg.WithQueryer(tx)) + err := tx.InsertWebhookSpec(ctx, jb.WebhookSpec) if err != nil { return errors.Wrap(err, "failed to create WebhookSpec") } @@ -362,11 +340,7 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { } sql := `INSERT INTO external_initiator_webhook_specs (external_initiator_id, webhook_spec_id, spec) VALUES (:external_initiator_id, :webhook_spec_id, :spec);` - query, args, err := tx.BindNamed(sql, jb.WebhookSpec.ExternalInitiatorWebhookSpecs) - if err != nil { - return errors.Wrap(err, "failed to bindquery for ExternalInitiatorWebhookSpecs") - } - if _, err = tx.Exec(query, args...); err != nil { + if _, err := tx.ds.NamedExecContext(ctx, sql, jb.WebhookSpec.ExternalInitiatorWebhookSpecs); err != nil { return errors.Wrap(err, "failed to create ExternalInitiatorWebhookSpecs") } } @@ -374,80 +348,58 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { if jb.BlockhashStoreSpec.EVMChainID == nil { return errors.New("evm chain id must be defined") } - var specID int32 - sql := `INSERT INTO blockhash_store_specs (coordinator_v1_address, coordinator_v2_address, coordinator_v2_plus_address, trusted_blockhash_store_address, trusted_blockhash_store_batch_size, wait_blocks, lookback_blocks, heartbeat_period, blockhash_store_address, poll_period, run_timeout, evm_chain_id, from_addresses, created_at, updated_at) - VALUES (:coordinator_v1_address, :coordinator_v2_address, :coordinator_v2_plus_address, :trusted_blockhash_store_address, :trusted_blockhash_store_batch_size, :wait_blocks, :lookback_blocks, :heartbeat_period, :blockhash_store_address, :poll_period, :run_timeout, :evm_chain_id, :from_addresses, NOW(), NOW()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, toBlockhashStoreSpecRow(jb.BlockhashStoreSpec)); err != nil { - return errors.Wrap(err, "failed to create BlockhashStore spec") + specID, err := tx.insertBlockhashStoreSpec(ctx, jb.BlockhashStoreSpec) + if err != nil { + return fmt.Errorf("failed to create BlockhashStoreSpec for jobSpec: %w", err) } jb.BlockhashStoreSpecID = &specID case BlockHeaderFeeder: if jb.BlockHeaderFeederSpec.EVMChainID == nil { return errors.New("evm chain id must be defined") } - var specID int32 - sql := `INSERT INTO block_header_feeder_specs (coordinator_v1_address, coordinator_v2_address, coordinator_v2_plus_address, wait_blocks, lookback_blocks, blockhash_store_address, batch_blockhash_store_address, poll_period, run_timeout, evm_chain_id, from_addresses, get_blockhashes_batch_size, store_blockhashes_batch_size, created_at, updated_at) - VALUES (:coordinator_v1_address, :coordinator_v2_address, :coordinator_v2_plus_address, :wait_blocks, :lookback_blocks, :blockhash_store_address, :batch_blockhash_store_address, :poll_period, :run_timeout, :evm_chain_id, :from_addresses, :get_blockhashes_batch_size, :store_blockhashes_batch_size, NOW(), NOW()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, toBlockHeaderFeederSpecRow(jb.BlockHeaderFeederSpec)); err != nil { - return errors.Wrap(err, "failed to create BlockHeaderFeeder spec") + specID, err := tx.insertBlockHeaderFeederSpec(ctx, jb.BlockHeaderFeederSpec) + if err != nil { + return fmt.Errorf("failed to create BlockHeaderFeederSpec for jobSpec: %w", err) } jb.BlockHeaderFeederSpecID = &specID case LegacyGasStationServer: if jb.LegacyGasStationServerSpec.EVMChainID == nil { return errors.New("evm chain id must be defined") } - var specID int32 - sql := `INSERT INTO legacy_gas_station_server_specs (forwarder_address, evm_chain_id, ccip_chain_selector, from_addresses, created_at, updated_at) - VALUES (:forwarder_address, :evm_chain_id, :ccip_chain_selector, :from_addresses, NOW(), NOW()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, toLegacyGasStationServerSpecRow(jb.LegacyGasStationServerSpec)); err != nil { - return errors.Wrap(err, "failed to create LegacyGasStationServer spec") + specID, err := tx.insertLegacyGasStationServerSpec(ctx, jb.LegacyGasStationServerSpec) + if err != nil { + return fmt.Errorf("failed to create LegacyGasStationServerSpec for jobSpec: %w", err) } jb.LegacyGasStationServerSpecID = &specID case LegacyGasStationSidecar: if jb.LegacyGasStationSidecarSpec.EVMChainID == nil { return errors.New("evm chain id must be defined") } - var specID int32 - sql := `INSERT INTO legacy_gas_station_sidecar_specs (forwarder_address, off_ramp_address, lookback_blocks, poll_period, run_timeout, evm_chain_id, ccip_chain_selector, created_at, updated_at) - VALUES (:forwarder_address, :off_ramp_address, :lookback_blocks, :poll_period, :run_timeout, :evm_chain_id, :ccip_chain_selector, NOW(), NOW()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, jb.LegacyGasStationSidecarSpec); err != nil { - return errors.Wrap(err, "failed to create LegacyGasStationSidecar spec") + specID, err := tx.insertLegacyGasStationSidecarSpec(ctx, jb.LegacyGasStationSidecarSpec) + if err != nil { + return fmt.Errorf("failed to create LegacyGasStationSidecarSpec for jobSpec: %w", err) } jb.LegacyGasStationSidecarSpecID = &specID case Bootstrap: - var specID int32 - sql := `INSERT INTO bootstrap_specs (contract_id, feed_id, relay, relay_config, monitoring_endpoint, - blockchain_timeout, contract_config_tracker_poll_interval, - contract_config_confirmations, created_at, updated_at) - VALUES (:contract_id, :feed_id, :relay, :relay_config, :monitoring_endpoint, - :blockchain_timeout, :contract_config_tracker_poll_interval, - :contract_config_confirmations, NOW(), NOW()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, jb.BootstrapSpec); err != nil { - return errors.Wrap(err, "failed to create BootstrapSpec for jobSpec") + specID, err := tx.insertBootstrapSpec(ctx, jb.BootstrapSpec) + if err != nil { + return fmt.Errorf("failed to create BootstrapSpec for jobSpec: %w", err) } jb.BootstrapSpecID = &specID case Gateway: - var specID int32 - sql := `INSERT INTO gateway_specs (gateway_config, created_at, updated_at) - VALUES (:gateway_config, NOW(), NOW()) - RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, jb.GatewaySpec); err != nil { - return errors.Wrap(err, "failed to create GatewaySpec for jobSpec") + specID, err := tx.insertGatewaySpec(ctx, jb.GatewaySpec) + if err != nil { + return fmt.Errorf("failed to create GatewaySpec for jobSpec: %w", err) } jb.GatewaySpecID = &specID case Stream: // 'stream' type has no associated spec, nothing to do here case Workflow: - var specID int32 sql := `INSERT INTO workflow_specs (workflow, workflow_id, workflow_owner, created_at, updated_at) VALUES (:workflow, :workflow_id, :workflow_owner, NOW(), NOW()) RETURNING id;` - if err := pg.PrepareQueryRowx(tx, sql, &specID, jb.WorkflowSpec); err != nil { + specID, err := tx.prepareQuerySpecID(ctx, sql, jb.WorkflowSpec) + if err != nil { return errors.Wrap(err, "failed to create WorkflowSpec for jobSpec") } jb.WorkflowSpecID = &specID @@ -455,14 +407,14 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { o.lggr.Panicf("Unsupported jb.Type: %v", jb.Type) } - pipelineSpecID, err := o.pipelineORM.CreateSpec(ctx, tx, p, jb.MaxTaskDuration) + pipelineSpecID, err := tx.pipelineORM.CreateSpec(ctx, p, jb.MaxTaskDuration) if err != nil { return errors.Wrap(err, "failed to create pipeline spec") } jb.PipelineSpecID = pipelineSpecID - err = o.InsertJob(jb, pg.WithQueryer(tx)) + err = tx.InsertJob(ctx, jb) jobID = jb.ID return errors.Wrap(err, "failed to insert job") }) @@ -470,7 +422,122 @@ func (o *orm) CreateJob(jb *Job, qopts ...pg.QOpt) error { return errors.Wrap(err, "CreateJobFailed") } - return o.findJob(jb, "id", jobID, qopts...) + return o.findJob(ctx, jb, "id", jobID) +} + +func (o *orm) prepareQuerySpecID(ctx context.Context, sql string, arg any) (specID int32, err error) { + var stmt *sqlx.NamedStmt + stmt, err = o.ds.PrepareNamedContext(ctx, sql) + if err != nil { + return + } + defer stmt.Close() + err = stmt.QueryRowxContext(ctx, arg).Scan(&specID) + return +} + +func (o *orm) insertDirectRequestSpec(ctx context.Context, spec *DirectRequestSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO direct_request_specs (contract_address, min_incoming_confirmations, requesters, min_contract_payment, evm_chain_id, created_at, updated_at) + VALUES (:contract_address, :min_incoming_confirmations, :requesters, :min_contract_payment, :evm_chain_id, now(), now()) + RETURNING id;`, spec) +} + +func (o *orm) insertFluxMonitorSpec(ctx context.Context, spec *FluxMonitorSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO flux_monitor_specs (contract_address, threshold, absolute_threshold, poll_timer_period, poll_timer_disabled, idle_timer_period, idle_timer_disabled, + drumbeat_schedule, drumbeat_random_delay, drumbeat_enabled, min_payment, evm_chain_id, created_at, updated_at) + VALUES (:contract_address, :threshold, :absolute_threshold, :poll_timer_period, :poll_timer_disabled, :idle_timer_period, :idle_timer_disabled, + :drumbeat_schedule, :drumbeat_random_delay, :drumbeat_enabled, :min_payment, :evm_chain_id, NOW(), NOW()) + RETURNING id;`, spec) +} + +func (o *orm) insertOCROracleSpec(ctx context.Context, spec *OCROracleSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO ocr_oracle_specs (contract_address, p2pv2_bootstrappers, is_bootstrap_peer, encrypted_ocr_key_bundle_id, transmitter_address, + observation_timeout, blockchain_timeout, contract_config_tracker_subscribe_interval, contract_config_tracker_poll_interval, contract_config_confirmations, evm_chain_id, + created_at, updated_at, database_timeout, observation_grace_period, contract_transmitter_transmit_timeout) + VALUES (:contract_address, :p2pv2_bootstrappers, :is_bootstrap_peer, :encrypted_ocr_key_bundle_id, :transmitter_address, + :observation_timeout, :blockchain_timeout, :contract_config_tracker_subscribe_interval, :contract_config_tracker_poll_interval, :contract_config_confirmations, :evm_chain_id, + NOW(), NOW(), :database_timeout, :observation_grace_period, :contract_transmitter_transmit_timeout) + RETURNING id;`, spec) +} + +func (o *orm) insertOCR2OracleSpec(ctx context.Context, spec *OCR2OracleSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO ocr2_oracle_specs (contract_id, feed_id, relay, relay_config, plugin_type, plugin_config, p2pv2_bootstrappers, ocr_key_bundle_id, transmitter_id, + blockchain_timeout, contract_config_tracker_poll_interval, contract_config_confirmations, + created_at, updated_at) + VALUES (:contract_id, :feed_id, :relay, :relay_config, :plugin_type, :plugin_config, :p2pv2_bootstrappers, :ocr_key_bundle_id, :transmitter_id, + :blockchain_timeout, :contract_config_tracker_poll_interval, :contract_config_confirmations, + NOW(), NOW()) + RETURNING id;`, spec) +} + +func (o *orm) insertKeeperSpec(ctx context.Context, spec *KeeperSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO keeper_specs (contract_address, from_address, evm_chain_id, created_at, updated_at) + VALUES (:contract_address, :from_address, :evm_chain_id, NOW(), NOW()) + RETURNING id;`, spec) +} + +func (o *orm) insertCronSpec(ctx context.Context, spec *CronSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO cron_specs (cron_schedule, created_at, updated_at) + VALUES (:cron_schedule, NOW(), NOW()) + RETURNING id;`, spec) +} + +func (o *orm) insertVRFSpec(ctx context.Context, spec *VRFSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO vrf_specs ( + coordinator_address, public_key, min_incoming_confirmations, + evm_chain_id, from_addresses, poll_period, requested_confs_delay, + request_timeout, chunk_size, batch_coordinator_address, batch_fulfillment_enabled, + batch_fulfillment_gas_multiplier, backoff_initial_delay, backoff_max_delay, gas_lane_price, + vrf_owner_address, custom_reverts_pipeline_enabled, + created_at, updated_at) + VALUES ( + :coordinator_address, :public_key, :min_incoming_confirmations, + :evm_chain_id, :from_addresses, :poll_period, :requested_confs_delay, + :request_timeout, :chunk_size, :batch_coordinator_address, :batch_fulfillment_enabled, + :batch_fulfillment_gas_multiplier, :backoff_initial_delay, :backoff_max_delay, :gas_lane_price, + :vrf_owner_address, :custom_reverts_pipeline_enabled, + NOW(), NOW()) + RETURNING id;`, toVRFSpecRow(spec)) +} + +func (o *orm) insertBlockhashStoreSpec(ctx context.Context, spec *BlockhashStoreSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO blockhash_store_specs (coordinator_v1_address, coordinator_v2_address, coordinator_v2_plus_address, trusted_blockhash_store_address, trusted_blockhash_store_batch_size, wait_blocks, lookback_blocks, heartbeat_period, blockhash_store_address, poll_period, run_timeout, evm_chain_id, from_addresses, created_at, updated_at) + VALUES (:coordinator_v1_address, :coordinator_v2_address, :coordinator_v2_plus_address, :trusted_blockhash_store_address, :trusted_blockhash_store_batch_size, :wait_blocks, :lookback_blocks, :heartbeat_period, :blockhash_store_address, :poll_period, :run_timeout, :evm_chain_id, :from_addresses, NOW(), NOW()) + RETURNING id;`, toBlockhashStoreSpecRow(spec)) +} + +func (o *orm) insertBlockHeaderFeederSpec(ctx context.Context, spec *BlockHeaderFeederSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO block_header_feeder_specs (coordinator_v1_address, coordinator_v2_address, coordinator_v2_plus_address, wait_blocks, lookback_blocks, blockhash_store_address, batch_blockhash_store_address, poll_period, run_timeout, evm_chain_id, from_addresses, get_blockhashes_batch_size, store_blockhashes_batch_size, created_at, updated_at) + VALUES (:coordinator_v1_address, :coordinator_v2_address, :coordinator_v2_plus_address, :wait_blocks, :lookback_blocks, :blockhash_store_address, :batch_blockhash_store_address, :poll_period, :run_timeout, :evm_chain_id, :from_addresses, :get_blockhashes_batch_size, :store_blockhashes_batch_size, NOW(), NOW()) + RETURNING id;`, toBlockHeaderFeederSpecRow(spec)) +} + +func (o *orm) insertLegacyGasStationServerSpec(ctx context.Context, spec *LegacyGasStationServerSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO legacy_gas_station_server_specs (forwarder_address, evm_chain_id, ccip_chain_selector, from_addresses, created_at, updated_at) + VALUES (:forwarder_address, :evm_chain_id, :ccip_chain_selector, :from_addresses, NOW(), NOW()) + RETURNING id;`, toLegacyGasStationServerSpecRow(spec)) +} + +func (o *orm) insertLegacyGasStationSidecarSpec(ctx context.Context, spec *LegacyGasStationSidecarSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO legacy_gas_station_sidecar_specs (forwarder_address, off_ramp_address, lookback_blocks, poll_period, run_timeout, evm_chain_id, ccip_chain_selector, created_at, updated_at) + VALUES (:forwarder_address, :off_ramp_address, :lookback_blocks, :poll_period, :run_timeout, :evm_chain_id, :ccip_chain_selector, NOW(), NOW()) + RETURNING id;`, spec) +} + +func (o *orm) insertBootstrapSpec(ctx context.Context, spec *BootstrapSpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO bootstrap_specs (contract_id, feed_id, relay, relay_config, monitoring_endpoint, + blockchain_timeout, contract_config_tracker_poll_interval, + contract_config_confirmations, created_at, updated_at) + VALUES (:contract_id, :feed_id, :relay, :relay_config, :monitoring_endpoint, + :blockchain_timeout, :contract_config_tracker_poll_interval, + :contract_config_confirmations, NOW(), NOW()) + RETURNING id;`, spec) +} + +func (o *orm) insertGatewaySpec(ctx context.Context, spec *GatewaySpec) (specID int32, err error) { + return o.prepareQuerySpecID(ctx, `INSERT INTO gateway_specs (gateway_config, created_at, updated_at) + VALUES (:gateway_config, NOW(), NOW()) + RETURNING id;`, spec) } // ValidateKeyStoreMatch confirms that the key has a valid match in the keystore @@ -531,17 +598,18 @@ func areSendingKeysDefined(ctx context.Context, jb *Job, keystore keystore.Maste return false, nil } -func (o *orm) InsertWebhookSpec(webhookSpec *WebhookSpec, qopts ...pg.QOpt) error { - q := o.q.WithOpts(qopts...) - query := `INSERT INTO webhook_specs (created_at, updated_at) +func (o *orm) InsertWebhookSpec(ctx context.Context, webhookSpec *WebhookSpec) error { + query, args, err := o.ds.BindNamed(`INSERT INTO webhook_specs (created_at, updated_at) VALUES (NOW(), NOW()) - RETURNING *;` - return q.GetNamed(query, webhookSpec, webhookSpec) + RETURNING *;`, webhookSpec) + if err != nil { + return fmt.Errorf("error binding arg: %w", err) + } + return o.ds.GetContext(ctx, webhookSpec, query, args...) } -func (o *orm) InsertJob(job *Job, qopts ...pg.QOpt) error { - q := o.q.WithOpts(qopts...) - return q.Transaction(func(querier pg.Queryer) error { +func (o *orm) InsertJob(ctx context.Context, job *Job) error { + return o.transact(ctx, false, func(tx *orm) error { var query string // if job has id, emplace otherwise insert with a new id. @@ -562,26 +630,30 @@ func (o *orm) InsertJob(job *Job, qopts ...pg.QOpt) error { :legacy_gas_station_server_spec_id, :legacy_gas_station_sidecar_spec_id, :workflow_spec_id, :external_job_id, :gas_limit, :forwarding_allowed, NOW()) RETURNING *;` } - err := q.GetNamed(query, job, job) + query, args, err := tx.ds.BindNamed(query, job) + if err != nil { + return fmt.Errorf("error binding arg: %w", err) + } + err = tx.ds.GetContext(ctx, job, query, args...) if err != nil { return err } // Always inserts the `job_pipeline_specs` record as primary, since this is the first one for the job. sqlStmt := `INSERT INTO job_pipeline_specs (job_id, pipeline_spec_id, is_primary) VALUES ($1, $2, true)` - _, err = q.Exec(sqlStmt, job.ID, job.PipelineSpecID) + _, err = tx.ds.ExecContext(ctx, sqlStmt, job.ID, job.PipelineSpecID) return errors.Wrap(err, "failed to insert job_pipeline_specs relationship") }) } // DeleteJob removes a job -func (o *orm) DeleteJob(id int32, qopts ...pg.QOpt) error { +func (o *orm) DeleteJob(ctx context.Context, id int32) error { o.lggr.Debugw("Deleting job", "jobID", id) // Added a 1-minute timeout to this query since this can take a long time as data increases. // This was added specifically due to an issue with a database that had a million of pipeline_runs and pipeline_task_runs // and this query was taking ~40secs. - qopts = append(qopts, pg.WithLongQueryTimeout()) - q := o.q.WithOpts(qopts...) + ctx, cancel := context.WithTimeout(sqlutil.WithoutDefaultTimeout(ctx), time.Minute) + defer cancel() query := ` WITH deleted_jobs AS ( DELETE FROM jobs WHERE id = $1 RETURNING @@ -643,8 +715,7 @@ func (o *orm) DeleteJob(id int32, qopts ...pg.QOpt) error { DELETE FROM job_pipeline_specs WHERE job_id IN (SELECT id FROM deleted_jobs) RETURNING pipeline_spec_id ) DELETE FROM pipeline_specs WHERE id IN (SELECT pipeline_spec_id FROM deleted_job_pipeline_specs)` - res, cancel, err := q.ExecQIter(query, id) - defer cancel() + res, err := o.ds.ExecContext(ctx, query, id) if err != nil { return errors.Wrap(err, "DeleteJob failed to delete job") } @@ -659,14 +730,13 @@ func (o *orm) DeleteJob(id int32, qopts ...pg.QOpt) error { return nil } -func (o *orm) RecordError(jobID int32, description string, qopts ...pg.QOpt) error { - q := o.q.WithOpts(qopts...) +func (o *orm) RecordError(ctx context.Context, jobID int32, description string) error { sql := `INSERT INTO job_spec_errors (job_id, description, occurrences, created_at, updated_at) VALUES ($1, $2, 1, $3, $3) ON CONFLICT (job_id, description) DO UPDATE SET occurrences = job_spec_errors.occurrences + 1, updated_at = excluded.updated_at` - err := q.ExecQ(sql, jobID, description, time.Now()) + _, err := o.ds.ExecContext(ctx, sql, jobID, description, time.Now()) // Noop if the job has been deleted. var pqErr *pgconn.PgError ok := errors.As(err, &pqErr) @@ -677,15 +747,13 @@ func (o *orm) RecordError(jobID int32, description string, qopts ...pg.QOpt) err } return err } -func (o *orm) TryRecordError(jobID int32, description string, qopts ...pg.QOpt) { - err := o.RecordError(jobID, description, qopts...) +func (o *orm) TryRecordError(ctx context.Context, jobID int32, description string) { + err := o.RecordError(ctx, jobID, description) o.lggr.ErrorIf(err, fmt.Sprintf("Error creating SpecError %v", description)) } func (o *orm) DismissError(ctx context.Context, ID int64) error { - q := o.q.WithOpts(pg.WithParentCtx(ctx)) - res, cancel, err := q.ExecQIter("DELETE FROM job_spec_errors WHERE id = $1", ID) - defer cancel() + res, err := o.ds.ExecContext(ctx, "DELETE FROM job_spec_errors WHERE id = $1", ID) if err != nil { return errors.Wrap(err, "failed to dismiss error") } @@ -699,35 +767,35 @@ func (o *orm) DismissError(ctx context.Context, ID int64) error { return nil } -func (o *orm) FindSpecError(id int64, qopts ...pg.QOpt) (SpecError, error) { +func (o *orm) FindSpecError(ctx context.Context, id int64) (SpecError, error) { stmt := `SELECT * FROM job_spec_errors WHERE id = $1;` specErr := new(SpecError) - err := o.q.WithOpts(qopts...).Get(specErr, stmt, id) + err := o.ds.GetContext(ctx, specErr, stmt, id) return *specErr, errors.Wrap(err, "FindSpecError failed") } -func (o *orm) FindJobs(offset, limit int) (jobs []Job, count int, err error) { - err = o.q.Transaction(func(tx pg.Queryer) error { +func (o *orm) FindJobs(ctx context.Context, offset, limit int) (jobs []Job, count int, err error) { + err = o.transact(ctx, false, func(tx *orm) error { sql := `SELECT count(*) FROM jobs;` - err = tx.QueryRowx(sql).Scan(&count) + err = tx.ds.QueryRowxContext(ctx, sql).Scan(&count) if err != nil { - return err + return fmt.Errorf("failed to query jobs count: %w", err) } sql = `SELECT jobs.*, job_pipeline_specs.pipeline_spec_id as pipeline_spec_id FROM jobs JOIN job_pipeline_specs ON (jobs.id = job_pipeline_specs.job_id) ORDER BY jobs.created_at DESC, jobs.id DESC OFFSET $1 LIMIT $2;` - err = tx.Select(&jobs, sql, offset, limit) + err = tx.ds.SelectContext(ctx, &jobs, sql, offset, limit) if err != nil { - return err + return fmt.Errorf("failed to select jobs: %w", err) } - err = LoadAllJobsTypes(tx, jobs) + err = tx.loadAllJobsTypes(ctx, jobs) if err != nil { - return err + return fmt.Errorf("failed to load job types: %w", err) } return nil @@ -820,32 +888,30 @@ func LoadConfigVarsOCR(evmOcrCfg evmconfig.OCR, ocrCfg OCRConfig, os OCROracleSp } func (o *orm) FindJobTx(ctx context.Context, id int32) (Job, error) { - ctx, cancel := context.WithTimeout(ctx, o.cfg.DefaultQueryTimeout()) - defer cancel() return o.FindJob(ctx, id) } // FindJob returns job by ID, with all relations preloaded func (o *orm) FindJob(ctx context.Context, id int32) (jb Job, err error) { - err = o.findJob(&jb, "id", id, pg.WithParentCtx(ctx)) + err = o.findJob(ctx, &jb, "id", id) return } // FindJobWithoutSpecErrors returns a job by ID, without loading Spec Errors preloaded -func (o *orm) FindJobWithoutSpecErrors(id int32) (jb Job, err error) { - err = o.q.Transaction(func(tx pg.Queryer) error { +func (o *orm) FindJobWithoutSpecErrors(ctx context.Context, id int32) (jb Job, err error) { + err = o.transact(ctx, true, func(tx *orm) error { stmt := "SELECT jobs.*, job_pipeline_specs.pipeline_spec_id as pipeline_spec_id FROM jobs JOIN job_pipeline_specs ON (jobs.id = job_pipeline_specs.job_id) WHERE jobs.id = $1 LIMIT 1" - err = tx.Get(&jb, stmt, id) + err = tx.ds.GetContext(ctx, &jb, stmt, id) if err != nil { return errors.Wrap(err, "failed to load job") } - if err = LoadAllJobTypes(tx, &jb); err != nil { + if err = tx.loadAllJobTypes(ctx, &jb); err != nil { return errors.Wrap(err, "failed to load job types") } return nil - }, pg.OptReadOnlyTx()) + }) if err != nil { return jb, errors.Wrap(err, "FindJobWithoutSpecErrors failed") } @@ -854,87 +920,76 @@ func (o *orm) FindJobWithoutSpecErrors(id int32) (jb Job, err error) { } // FindSpecErrorsByJobIDs returns all jobs spec errors by jobs IDs -func (o *orm) FindSpecErrorsByJobIDs(ids []int32, qopts ...pg.QOpt) ([]SpecError, error) { +func (o *orm) FindSpecErrorsByJobIDs(ctx context.Context, ids []int32) ([]SpecError, error) { stmt := `SELECT * FROM job_spec_errors WHERE job_id = ANY($1);` var specErrs []SpecError - err := o.q.WithOpts(qopts...).Select(&specErrs, stmt, ids) + err := o.ds.SelectContext(ctx, &specErrs, stmt, ids) return specErrs, errors.Wrap(err, "FindSpecErrorsByJobIDs failed") } -func (o *orm) FindJobByExternalJobID(externalJobID uuid.UUID, qopts ...pg.QOpt) (jb Job, err error) { - err = o.findJob(&jb, "external_job_id", externalJobID, qopts...) +func (o *orm) FindJobByExternalJobID(ctx context.Context, externalJobID uuid.UUID) (jb Job, err error) { + err = o.findJob(ctx, &jb, "external_job_id", externalJobID) return } // FindJobIDByAddress - finds a job id by contract address. Currently only OCR and FM jobs are supported -func (o *orm) FindJobIDByAddress(address evmtypes.EIP55Address, evmChainID *big.Big, qopts ...pg.QOpt) (jobID int32, err error) { - q := o.q.WithOpts(qopts...) - err = q.Transaction(func(tx pg.Queryer) error { - stmt := ` +func (o *orm) FindJobIDByAddress(ctx context.Context, address evmtypes.EIP55Address, evmChainID *big.Big) (jobID int32, err error) { + stmt := ` SELECT jobs.id FROM jobs LEFT JOIN ocr_oracle_specs ocrspec on ocrspec.contract_address = $1 AND (ocrspec.evm_chain_id = $2 OR ocrspec.evm_chain_id IS NULL) AND ocrspec.id = jobs.ocr_oracle_spec_id LEFT JOIN flux_monitor_specs fmspec on fmspec.contract_address = $1 AND (fmspec.evm_chain_id = $2 OR fmspec.evm_chain_id IS NULL) AND fmspec.id = jobs.flux_monitor_spec_id WHERE ocrspec.id IS NOT NULL OR fmspec.id IS NOT NULL ` - err = tx.Get(&jobID, stmt, address, evmChainID) - + err = o.ds.GetContext(ctx, &jobID, stmt, address, evmChainID) + if err != nil { if !errors.Is(err, sql.ErrNoRows) { - if err != nil { - return errors.Wrap(err, "error searching for job by contract address") - } - return nil + err = errors.Wrap(err, "error searching for job by contract address") } + err = errors.Wrap(err, "FindJobIDByAddress failed") + return + } - return err - }) - - return jobID, errors.Wrap(err, "FindJobIDByAddress failed") + return } -func (o *orm) FindOCR2JobIDByAddress(contractID string, feedID *common.Hash, qopts ...pg.QOpt) (jobID int32, err error) { - q := o.q.WithOpts(qopts...) - err = q.Transaction(func(tx pg.Queryer) error { - // NOTE: We want to explicitly match on NULL feed_id hence usage of `IS - // NOT DISTINCT FROM` instead of `=` - stmt := ` +func (o *orm) FindOCR2JobIDByAddress(ctx context.Context, contractID string, feedID *common.Hash) (jobID int32, err error) { + // NOTE: We want to explicitly match on NULL feed_id hence usage of `IS + // NOT DISTINCT FROM` instead of `=` + stmt := ` SELECT jobs.id FROM jobs LEFT JOIN ocr2_oracle_specs ocr2spec on ocr2spec.contract_id = $1 AND ocr2spec.feed_id IS NOT DISTINCT FROM $2 AND ocr2spec.id = jobs.ocr2_oracle_spec_id LEFT JOIN bootstrap_specs bs on bs.contract_id = $1 AND bs.feed_id IS NOT DISTINCT FROM $2 AND bs.id = jobs.bootstrap_spec_id WHERE ocr2spec.id IS NOT NULL OR bs.id IS NOT NULL ` - err = tx.Get(&jobID, stmt, contractID, feedID) - + err = o.ds.GetContext(ctx, &jobID, stmt, contractID, feedID) + if err != nil { if !errors.Is(err, sql.ErrNoRows) { - if err != nil { - return errors.Wrapf(err, "error searching for job by contract id=%s and feed id=%s", contractID, feedID) - } - return nil + err = errors.Wrapf(err, "error searching for job by contract id=%s and feed id=%s", contractID, feedID) } + err = errors.Wrap(err, "FindOCR2JobIDByAddress failed") + return + } - return err - }) - - return jobID, errors.Wrap(err, "FindOCR2JobIDByAddress failed") + return } -func (o *orm) findJob(jb *Job, col string, arg interface{}, qopts ...pg.QOpt) error { - q := o.q.WithOpts(qopts...) - err := q.Transaction(func(tx pg.Queryer) error { +func (o *orm) findJob(ctx context.Context, jb *Job, col string, arg interface{}) error { + err := o.transact(ctx, false, func(tx *orm) error { sql := fmt.Sprintf(`SELECT jobs.*, job_pipeline_specs.pipeline_spec_id FROM jobs JOIN job_pipeline_specs ON (jobs.id = job_pipeline_specs.job_id) WHERE jobs.%s = $1 AND job_pipeline_specs.is_primary = true LIMIT 1`, col) - err := tx.Get(jb, sql, arg) + err := tx.ds.GetContext(ctx, jb, sql, arg) if err != nil { return errors.Wrap(err, "failed to load job") } - if err = LoadAllJobTypes(tx, jb); err != nil { + if err = tx.loadAllJobTypes(ctx, jb); err != nil { return err } - return loadJobSpecErrors(tx, jb) + return tx.loadJobSpecErrors(ctx, jb) }) if err != nil { return errors.Wrap(err, "findJob failed") @@ -942,62 +997,62 @@ func (o *orm) findJob(jb *Job, col string, arg interface{}, qopts ...pg.QOpt) er return nil } -func (o *orm) FindJobIDsWithBridge(name string) (jids []int32, err error) { - err = o.q.Transaction(func(tx pg.Queryer) error { - query := `SELECT +func (o *orm) FindJobIDsWithBridge(ctx context.Context, name string) (jids []int32, err error) { + query := `SELECT jobs.id, pipeline_specs.dot_dag_source FROM jobs JOIN job_pipeline_specs ON job_pipeline_specs.job_id = jobs.id JOIN pipeline_specs ON pipeline_specs.id = job_pipeline_specs.pipeline_spec_id WHERE pipeline_specs.dot_dag_source ILIKE '%' || $1 || '%' ORDER BY id` + var rows *sqlx.Rows + rows, err = o.ds.QueryxContext(ctx, query, name) + if err != nil { + return + } + defer rows.Close() + var ids []int32 + var sources []string + for rows.Next() { + var id int32 + var source string + if err = rows.Scan(&id, &source); err != nil { + return + } + ids = append(jids, id) + sources = append(sources, source) + } + if err = rows.Err(); err != nil { + return + } - var rows *sqlx.Rows - rows, err = tx.Queryx(query, name) + for i, id := range ids { + var p *pipeline.Pipeline + p, err = pipeline.Parse(sources[i]) if err != nil { - return err + return nil, errors.Wrapf(err, "could not parse dag for job %d", id) } - defer rows.Close() - var ids []int32 - var sources []string - for rows.Next() { - var id int32 - var source string - if err = rows.Scan(&id, &source); err != nil { - return err - } - ids = append(jids, id) - sources = append(sources, source) - } - - for i, id := range ids { - var p *pipeline.Pipeline - p, err = pipeline.Parse(sources[i]) - if err != nil { - return errors.Wrapf(err, "could not parse dag for job %d", id) - } - for _, task := range p.Tasks { - if task.Type() == pipeline.TaskTypeBridge { - if task.(*pipeline.BridgeTask).Name == name { - jids = append(jids, id) - } + for _, task := range p.Tasks { + if task.Type() == pipeline.TaskTypeBridge { + if task.(*pipeline.BridgeTask).Name == name { + jids = append(jids, id) } } } - return nil - }) - return jids, errors.Wrap(err, "FindJobIDsWithBridge failed") + } + + return } // PipelineRunsByJobsIDs returns pipeline runs for multiple jobs, not preloading data -func (o *orm) PipelineRunsByJobsIDs(ids []int32) (runs []pipeline.Run, err error) { - err = o.q.Transaction(func(tx pg.Queryer) error { +func (o *orm) PipelineRunsByJobsIDs(ctx context.Context, ids []int32) (runs []pipeline.Run, err error) { + err = o.transact(ctx, false, func(tx *orm) error { stmt := `SELECT pipeline_runs.* FROM pipeline_runs INNER JOIN job_pipeline_specs ON pipeline_runs.pipeline_spec_id = job_pipeline_specs.pipeline_spec_id WHERE jobs.id = ANY($1) ORDER BY pipeline_runs.created_at DESC, pipeline_runs.id DESC;` - if err = tx.Select(&runs, stmt, ids); err != nil { + if err = tx.ds.SelectContext(ctx, &runs, stmt, ids); err != nil { return errors.Wrap(err, "error loading runs") } - runs, err = o.loadPipelineRunsRelations(runs, tx) + runs, err = tx.loadPipelineRunsRelations(ctx, runs) return err }) @@ -1005,11 +1060,11 @@ func (o *orm) PipelineRunsByJobsIDs(ids []int32) (runs []pipeline.Run, err error return runs, errors.Wrap(err, "PipelineRunsByJobsIDs failed") } -func (o *orm) loadPipelineRunIDs(jobID *int32, offset, limit int, tx pg.Queryer) (ids []int64, err error) { +func (o *orm) loadPipelineRunIDs(ctx context.Context, jobID *int32, offset, limit int) (ids []int64, err error) { lggr := logger.Sugared(o.lggr) var res sql.NullInt64 - if err = tx.Get(&res, "SELECT MAX(id) FROM pipeline_runs"); err != nil { + if err = o.ds.GetContext(ctx, &res, "SELECT MAX(id) FROM pipeline_runs"); err != nil { err = errors.Wrap(err, "error while loading runs") return } else if !res.Valid { @@ -1037,7 +1092,7 @@ func (o *orm) loadPipelineRunIDs(jobID *int32, offset, limit int, tx pg.Queryer) for n := int64(1000); maxID > 0 && len(ids) < limit; n *= 2 { var batch []int64 minID := maxID - n - if err = tx.Select(&batch, stmt, offset, limit-len(ids), minID, maxID); err != nil { + if err = o.ds.SelectContext(ctx, &batch, stmt, offset, limit-len(ids), minID, maxID); err != nil { err = errors.Wrap(err, "error loading runs") return } @@ -1050,7 +1105,7 @@ func (o *orm) loadPipelineRunIDs(jobID *int32, offset, limit int, tx pg.Queryer) var skipped int // If no rows were returned, we need to know whether there were any ids skipped // in this batch due to the offset, and reduce it for the next batch - err = tx.Get(&skipped, + err = o.ds.GetContext(ctx, &skipped, fmt.Sprintf( `SELECT COUNT(p.id) FROM pipeline_runs AS p %s p.id >= $1 AND p.id <= $2`, filter, ), minID, maxID, @@ -1074,63 +1129,60 @@ func (o *orm) loadPipelineRunIDs(jobID *int32, offset, limit int, tx pg.Queryer) return } -func (o *orm) FindTaskResultByRunIDAndTaskName(runID int64, taskName string, qopts ...pg.QOpt) (result []byte, err error) { - q := o.q.WithOpts(qopts...) - err = q.Transaction(func(tx pg.Queryer) error { - stmt := fmt.Sprintf("SELECT * FROM pipeline_task_runs WHERE pipeline_run_id = $1 AND dot_id = '%s';", taskName) +func (o *orm) FindTaskResultByRunIDAndTaskName(ctx context.Context, runID int64, taskName string) (result []byte, err error) { + stmt := fmt.Sprintf("SELECT * FROM pipeline_task_runs WHERE pipeline_run_id = $1 AND dot_id = '%s';", taskName) - var taskRuns []pipeline.TaskRun - if errB := tx.Select(&taskRuns, stmt, runID); errB != nil { - return errB - } - if len(taskRuns) == 0 { - return fmt.Errorf("can't find task run with id: %v, taskName: %v", runID, taskName) - } - if len(taskRuns) > 1 { - o.lggr.Errorf("found multiple task runs with id: %v, taskName: %v. Using the first one.", runID, taskName) - } - taskRun := taskRuns[0] - if !taskRun.Error.IsZero() { - return errors.New(taskRun.Error.ValueOrZero()) - } - resBytes, errB := taskRun.Output.MarshalJSON() - if errB != nil { - return errB - } - result = resBytes - return nil - }) - return result, errors.Wrap(err, "failed") + var taskRuns []pipeline.TaskRun + if errB := o.ds.SelectContext(ctx, &taskRuns, stmt, runID); errB != nil { + return nil, errB + } + if len(taskRuns) == 0 { + return nil, fmt.Errorf("can't find task run with id: %v, taskName: %v", runID, taskName) + } + if len(taskRuns) > 1 { + o.lggr.Errorf("found multiple task runs with id: %v, taskName: %v. Using the first one.", runID, taskName) + } + taskRun := taskRuns[0] + if !taskRun.Error.IsZero() { + return nil, errors.New(taskRun.Error.ValueOrZero()) + } + resBytes, errB := taskRun.Output.MarshalJSON() + if errB != nil { + return + } + result = resBytes + + return } // FindPipelineRunIDsByJobID fetches the ids of pipeline runs for a job. -func (o *orm) FindPipelineRunIDsByJobID(jobID int32, offset, limit int) (ids []int64, err error) { - err = o.q.Transaction(func(tx pg.Queryer) error { - ids, err = o.loadPipelineRunIDs(&jobID, offset, limit, tx) +func (o *orm) FindPipelineRunIDsByJobID(ctx context.Context, jobID int32, offset, limit int) (ids []int64, err error) { + err = o.transact(ctx, false, func(tx *orm) error { + ids, err = tx.loadPipelineRunIDs(ctx, &jobID, offset, limit) return err }) return ids, errors.Wrap(err, "FindPipelineRunIDsByJobID failed") } -func (o *orm) loadPipelineRunsByID(ids []int64, tx pg.Queryer) (runs []pipeline.Run, err error) { +func (o *orm) loadPipelineRunsByID(ctx context.Context, ids []int64) (runs []pipeline.Run, err error) { stmt := ` SELECT pipeline_runs.* FROM pipeline_runs WHERE id = ANY($1) ORDER BY created_at DESC, id DESC ` - if err = tx.Select(&runs, stmt, ids); err != nil { + if err = o.ds.SelectContext(ctx, &runs, stmt, ids); err != nil { err = errors.Wrap(err, "error loading runs") return } - return o.loadPipelineRunsRelations(runs, tx) + return o.loadPipelineRunsRelations(ctx, runs) } // FindPipelineRunsByIDs returns pipeline runs with the ids. -func (o *orm) FindPipelineRunsByIDs(ids []int64) (runs []pipeline.Run, err error) { - err = o.q.Transaction(func(tx pg.Queryer) error { - runs, err = o.loadPipelineRunsByID(ids, tx) +func (o *orm) FindPipelineRunsByIDs(ctx context.Context, ids []int64) (runs []pipeline.Run, err error) { + err = o.transact(ctx, false, func(tx *orm) error { + runs, err = tx.loadPipelineRunsByID(ctx, ids) return err }) @@ -1138,21 +1190,21 @@ func (o *orm) FindPipelineRunsByIDs(ids []int64) (runs []pipeline.Run, err error } // FindPipelineRunByID returns pipeline run with the id. -func (o *orm) FindPipelineRunByID(id int64) (pipeline.Run, error) { +func (o *orm) FindPipelineRunByID(ctx context.Context, id int64) (pipeline.Run, error) { var run pipeline.Run - err := o.q.Transaction(func(tx pg.Queryer) error { + err := o.transact(ctx, false, func(tx *orm) error { stmt := ` SELECT pipeline_runs.* FROM pipeline_runs WHERE id = $1 ` - if err := tx.Get(&run, stmt, id); err != nil { + if err := tx.ds.GetContext(ctx, &run, stmt, id); err != nil { return errors.Wrap(err, "error loading run") } - runs, err := o.loadPipelineRunsRelations([]pipeline.Run{run}, tx) + runs, err := tx.loadPipelineRunsRelations(ctx, []pipeline.Run{run}) run = runs[0] @@ -1163,30 +1215,24 @@ WHERE id = $1 } // CountPipelineRunsByJobID returns the total number of pipeline runs for a job. -func (o *orm) CountPipelineRunsByJobID(jobID int32) (count int32, err error) { - err = o.q.Transaction(func(tx pg.Queryer) error { - stmt := "SELECT COUNT(*) FROM pipeline_runs JOIN job_pipeline_specs USING (pipeline_spec_id) WHERE job_pipeline_specs.job_id = $1" - if err = tx.Get(&count, stmt, jobID); err != nil { - return errors.Wrap(err, "error counting runs") - } - - return err - }) +func (o *orm) CountPipelineRunsByJobID(ctx context.Context, jobID int32) (count int32, err error) { + stmt := "SELECT COUNT(*) FROM pipeline_runs JOIN job_pipeline_specs USING (pipeline_spec_id) WHERE job_pipeline_specs.job_id = $1" + err = o.ds.GetContext(ctx, &count, stmt, jobID) return count, errors.Wrap(err, "CountPipelineRunsByJobID failed") } -func (o *orm) FindJobsByPipelineSpecIDs(ids []int32) ([]Job, error) { +func (o *orm) FindJobsByPipelineSpecIDs(ctx context.Context, ids []int32) ([]Job, error) { var jbs []Job - err := o.q.Transaction(func(tx pg.Queryer) error { + err := o.transact(ctx, false, func(tx *orm) error { stmt := `SELECT jobs.*, job_pipeline_specs.pipeline_spec_id FROM jobs JOIN job_pipeline_specs ON (jobs.id = job_pipeline_specs.job_id) WHERE job_pipeline_specs.pipeline_spec_id = ANY($1) ORDER BY jobs.id ASC ` - if err := tx.Select(&jbs, stmt, ids); err != nil { + if err := tx.ds.SelectContext(ctx, &jbs, stmt, ids); err != nil { return errors.Wrap(err, "error fetching jobs by pipeline spec IDs") } - err := LoadAllJobsTypes(tx, jbs) + err := tx.loadAllJobsTypes(ctx, jbs) if err != nil { return err } @@ -1199,20 +1245,20 @@ func (o *orm) FindJobsByPipelineSpecIDs(ids []int32) ([]Job, error) { // PipelineRuns returns pipeline runs for a job, with spec and taskruns loaded, latest first // If jobID is nil, returns all pipeline runs -func (o *orm) PipelineRuns(jobID *int32, offset, size int) (runs []pipeline.Run, count int, err error) { +func (o *orm) PipelineRuns(ctx context.Context, jobID *int32, offset, size int) (runs []pipeline.Run, count int, err error) { var filter string if jobID != nil { filter = fmt.Sprintf("JOIN job_pipeline_specs USING(pipeline_spec_id) WHERE job_pipeline_specs.job_id = %d", *jobID) } - err = o.q.Transaction(func(tx pg.Queryer) error { + err = o.transact(ctx, false, func(tx *orm) error { sql := fmt.Sprintf(`SELECT count(*) FROM pipeline_runs %s`, filter) - if err = tx.QueryRowx(sql).Scan(&count); err != nil { + if err = tx.ds.QueryRowxContext(ctx, sql).Scan(&count); err != nil { return errors.Wrap(err, "error counting runs") } var ids []int64 - ids, err = o.loadPipelineRunIDs(jobID, offset, size, tx) - runs, err = o.loadPipelineRunsByID(ids, tx) + ids, err = tx.loadPipelineRunIDs(ctx, jobID, offset, size) + runs, err = tx.loadPipelineRunsByID(ctx, ids) return err }) @@ -1220,7 +1266,7 @@ func (o *orm) PipelineRuns(jobID *int32, offset, size int) (runs []pipeline.Run, return runs, count, errors.Wrap(err, "PipelineRuns failed") } -func (o *orm) loadPipelineRunsRelations(runs []pipeline.Run, tx pg.Queryer) ([]pipeline.Run, error) { +func (o *orm) loadPipelineRunsRelations(ctx context.Context, runs []pipeline.Run) ([]pipeline.Run, error) { // Postload PipelineSpecs // TODO: We should pull this out into a generic preload function once go has generics specM := make(map[int32]pipeline.Spec) @@ -1235,7 +1281,7 @@ func (o *orm) loadPipelineRunsRelations(runs []pipeline.Run, tx pg.Queryer) ([]p } stmt := `SELECT pipeline_specs.*, job_pipeline_specs.job_id AS job_id FROM pipeline_specs JOIN job_pipeline_specs ON pipeline_specs.id = job_pipeline_specs.pipeline_spec_id WHERE pipeline_specs.id = ANY($1);` var specs []pipeline.Spec - if err := o.q.Select(&specs, stmt, specIDs); err != nil { + if err := o.ds.SelectContext(ctx, &specs, stmt, specIDs); err != nil { return nil, errors.Wrap(err, "error loading specs") } for _, spec := range specs { @@ -1254,7 +1300,7 @@ func (o *orm) loadPipelineRunsRelations(runs []pipeline.Run, tx pg.Queryer) ([]p } var taskRuns []pipeline.TaskRun stmt = `SELECT * FROM pipeline_task_runs WHERE pipeline_run_id = ANY($1) ORDER BY pipeline_run_id, created_at, id;` - if err := tx.Select(&taskRuns, stmt, runIDs); err != nil { + if err := o.ds.SelectContext(ctx, &taskRuns, stmt, runIDs); err != nil { return nil, errors.Wrap(err, "error loading pipeline_task_runs") } for _, taskRun := range taskRuns { @@ -1268,9 +1314,9 @@ func (o *orm) loadPipelineRunsRelations(runs []pipeline.Run, tx pg.Queryer) ([]p // NOTE: N+1 query, be careful of performance // This is not easily fixable without complicating the logic a lot, since we // only use it in the GUI it's probably acceptable -func LoadAllJobsTypes(tx pg.Queryer, jobs []Job) error { +func (o *orm) loadAllJobsTypes(ctx context.Context, jobs []Job) error { for i := range jobs { - err := LoadAllJobTypes(tx, &jobs[i]) + err := o.loadAllJobTypes(ctx, &jobs[i]) if err != nil { return err } @@ -1278,28 +1324,28 @@ func LoadAllJobsTypes(tx pg.Queryer, jobs []Job) error { return nil } -func LoadAllJobTypes(tx pg.Queryer, job *Job) error { +func (o *orm) loadAllJobTypes(ctx context.Context, job *Job) error { return multierr.Combine( - loadJobPipelineSpec(tx, job, &job.PipelineSpecID), - loadJobType(tx, job, "FluxMonitorSpec", "flux_monitor_specs", job.FluxMonitorSpecID), - loadJobType(tx, job, "DirectRequestSpec", "direct_request_specs", job.DirectRequestSpecID), - loadJobType(tx, job, "OCROracleSpec", "ocr_oracle_specs", job.OCROracleSpecID), - loadJobType(tx, job, "OCR2OracleSpec", "ocr2_oracle_specs", job.OCR2OracleSpecID), - loadJobType(tx, job, "KeeperSpec", "keeper_specs", job.KeeperSpecID), - loadJobType(tx, job, "CronSpec", "cron_specs", job.CronSpecID), - loadJobType(tx, job, "WebhookSpec", "webhook_specs", job.WebhookSpecID), - loadVRFJob(tx, job, job.VRFSpecID), - loadBlockhashStoreJob(tx, job, job.BlockhashStoreSpecID), - loadBlockHeaderFeederJob(tx, job, job.BlockHeaderFeederSpecID), - loadLegacyGasStationServerJob(tx, job, job.LegacyGasStationServerSpecID), - loadJobType(tx, job, "LegacyGasStationSidecarSpec", "legacy_gas_station_sidecar_specs", job.LegacyGasStationSidecarSpecID), - loadJobType(tx, job, "BootstrapSpec", "bootstrap_specs", job.BootstrapSpecID), - loadJobType(tx, job, "GatewaySpec", "gateway_specs", job.GatewaySpecID), - loadJobType(tx, job, "WorkflowSpec", "workflow_specs", job.WorkflowSpecID), + o.loadJobPipelineSpec(ctx, job, &job.PipelineSpecID), + o.loadJobType(ctx, job, "FluxMonitorSpec", "flux_monitor_specs", job.FluxMonitorSpecID), + o.loadJobType(ctx, job, "DirectRequestSpec", "direct_request_specs", job.DirectRequestSpecID), + o.loadJobType(ctx, job, "OCROracleSpec", "ocr_oracle_specs", job.OCROracleSpecID), + o.loadJobType(ctx, job, "OCR2OracleSpec", "ocr2_oracle_specs", job.OCR2OracleSpecID), + o.loadJobType(ctx, job, "KeeperSpec", "keeper_specs", job.KeeperSpecID), + o.loadJobType(ctx, job, "CronSpec", "cron_specs", job.CronSpecID), + o.loadJobType(ctx, job, "WebhookSpec", "webhook_specs", job.WebhookSpecID), + o.loadVRFJob(ctx, job, job.VRFSpecID), + o.loadBlockhashStoreJob(ctx, job, job.BlockhashStoreSpecID), + o.loadBlockHeaderFeederJob(ctx, job, job.BlockHeaderFeederSpecID), + o.loadLegacyGasStationServerJob(ctx, job, job.LegacyGasStationServerSpecID), + o.loadJobType(ctx, job, "LegacyGasStationSidecarSpec", "legacy_gas_station_sidecar_specs", job.LegacyGasStationSidecarSpecID), + o.loadJobType(ctx, job, "BootstrapSpec", "bootstrap_specs", job.BootstrapSpecID), + o.loadJobType(ctx, job, "GatewaySpec", "gateway_specs", job.GatewaySpecID), + o.loadJobType(ctx, job, "WorkflowSpec", "workflow_specs", job.WorkflowSpecID), ) } -func loadJobType(tx pg.Queryer, job *Job, field, table string, id *int32) error { +func (o *orm) loadJobType(ctx context.Context, job *Job, field, table string, id *int32) error { if id == nil { return nil } @@ -1312,7 +1358,7 @@ func loadJobType(tx pg.Queryer, job *Job, field, table string, id *int32) error destVal := reflect.New(t) dest := destVal.Interface() - err := tx.Get(dest, fmt.Sprintf(`SELECT * FROM %s WHERE id = $1`, table), *id) + err := o.ds.GetContext(ctx, dest, fmt.Sprintf(`SELECT * FROM %s WHERE id = $1`, table), *id) if err != nil { return errors.Wrapf(err, "failed to load job type %s with id %d", table, *id) @@ -1321,7 +1367,7 @@ func loadJobType(tx pg.Queryer, job *Job, field, table string, id *int32) error return nil } -func loadJobPipelineSpec(tx pg.Queryer, job *Job, id *int32) error { +func (o *orm) loadJobPipelineSpec(ctx context.Context, job *Job, id *int32) error { if id == nil { return nil } @@ -1329,7 +1375,8 @@ func loadJobPipelineSpec(tx pg.Queryer, job *Job, id *int32) error { if job.PipelineSpec != nil { pipelineSpecRow = job.PipelineSpec } - err := tx.Get( + err := o.ds.GetContext( + ctx, pipelineSpecRow, `SELECT pipeline_specs.*, job_pipeline_specs.job_id as job_id FROM pipeline_specs @@ -1344,13 +1391,13 @@ func loadJobPipelineSpec(tx pg.Queryer, job *Job, id *int32) error { return nil } -func loadVRFJob(tx pg.Queryer, job *Job, id *int32) error { +func (o *orm) loadVRFJob(ctx context.Context, job *Job, id *int32) error { if id == nil { return nil } var row vrfSpecRow - err := tx.Get(&row, `SELECT * FROM vrf_specs WHERE id = $1`, *id) + err := o.ds.GetContext(ctx, &row, `SELECT * FROM vrf_specs WHERE id = $1`, *id) if err != nil { return errors.Wrapf(err, `failed to load job type VRFSpec with id %d`, *id) } @@ -1383,13 +1430,13 @@ func (r vrfSpecRow) toVRFSpec() *VRFSpec { return r.VRFSpec } -func loadBlockhashStoreJob(tx pg.Queryer, job *Job, id *int32) error { +func (o *orm) loadBlockhashStoreJob(ctx context.Context, job *Job, id *int32) error { if id == nil { return nil } var row blockhashStoreSpecRow - err := tx.Get(&row, `SELECT * FROM blockhash_store_specs WHERE id = $1`, *id) + err := o.ds.GetContext(ctx, &row, `SELECT * FROM blockhash_store_specs WHERE id = $1`, *id) if err != nil { return errors.Wrapf(err, `failed to load job type BlockhashStoreSpec with id %d`, *id) } @@ -1422,13 +1469,13 @@ func (r blockhashStoreSpecRow) toBlockhashStoreSpec() *BlockhashStoreSpec { return r.BlockhashStoreSpec } -func loadBlockHeaderFeederJob(tx pg.Queryer, job *Job, id *int32) error { +func (o *orm) loadBlockHeaderFeederJob(ctx context.Context, job *Job, id *int32) error { if id == nil { return nil } var row blockHeaderFeederSpecRow - err := tx.Get(&row, `SELECT * FROM block_header_feeder_specs WHERE id = $1`, *id) + err := o.ds.GetContext(ctx, &row, `SELECT * FROM block_header_feeder_specs WHERE id = $1`, *id) if err != nil { return errors.Wrapf(err, `failed to load job type BlockHeaderFeederSpec with id %d`, *id) } @@ -1461,13 +1508,13 @@ func (r blockHeaderFeederSpecRow) toBlockHeaderFeederSpec() *BlockHeaderFeederSp return r.BlockHeaderFeederSpec } -func loadLegacyGasStationServerJob(tx pg.Queryer, job *Job, id *int32) error { +func (o *orm) loadLegacyGasStationServerJob(ctx context.Context, job *Job, id *int32) error { if id == nil { return nil } var row legacyGasStationServerSpecRow - err := tx.Get(&row, `SELECT * FROM legacy_gas_station_server_specs WHERE id = $1`, *id) + err := o.ds.GetContext(ctx, &row, `SELECT * FROM legacy_gas_station_server_specs WHERE id = $1`, *id) if err != nil { return errors.Wrapf(err, `failed to load job type LegacyGasStationServerSpec with id %d`, *id) } @@ -1500,6 +1547,6 @@ func (r legacyGasStationServerSpecRow) toLegacyGasStationServerSpec() *LegacyGas return r.LegacyGasStationServerSpec } -func loadJobSpecErrors(tx pg.Queryer, jb *Job) error { - return errors.Wrapf(tx.Select(&jb.JobSpecErrors, `SELECT * FROM job_spec_errors WHERE job_id = $1`, jb.ID), "failed to load job spec errors for job %d", jb.ID) +func (o *orm) loadJobSpecErrors(ctx context.Context, jb *Job) error { + return errors.Wrapf(o.ds.SelectContext(ctx, &jb.JobSpecErrors, `SELECT * FROM job_spec_errors WHERE job_id = $1`, jb.ID), "failed to load job spec errors for job %d", jb.ID) } diff --git a/core/services/job/orm_test.go b/core/services/job/orm_test.go index fb0e846b9d2..11f3e94f2d4 100644 --- a/core/services/job/orm_test.go +++ b/core/services/job/orm_test.go @@ -6,8 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" @@ -16,13 +15,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/store/models" ) -func NewTestORM(t *testing.T, db *sqlx.DB, pipelineORM pipeline.ORM, bridgeORM bridges.ORM, keyStore keystore.Master, cfg pg.QConfig) job.ORM { - o := job.NewORM(db, pipelineORM, bridgeORM, keyStore, logger.TestLogger(t), cfg) +func NewTestORM(t *testing.T, ds sqlutil.DataSource, pipelineORM pipeline.ORM, bridgeORM bridges.ORM, keyStore keystore.Master) job.ORM { + o := job.NewORM(ds, pipelineORM, bridgeORM, keyStore, logger.TestLogger(t)) t.Cleanup(func() { assert.NoError(t, o.Close()) }) return o } diff --git a/core/services/job/runner_integration_test.go b/core/services/job/runner_integration_test.go index 26a78a8624e..cdfe39dd17f 100644 --- a/core/services/job/runner_integration_test.go +++ b/core/services/job/runner_integration_test.go @@ -89,7 +89,7 @@ func TestRunner(t *testing.T) { c := clhttptest.NewTestLocalOnlyHTTPClient() runner := pipeline.NewRunner(pipelineORM, btORM, config.JobPipeline(), config.WebServer(), legacyChains, nil, nil, logger.TestLogger(t), c, c) - jobORM := NewTestORM(t, db, pipelineORM, btORM, keyStore, config.Database()) + jobORM := NewTestORM(t, db, pipelineORM, btORM, keyStore) t.Cleanup(func() { assert.NoError(t, jobORM.Close()) }) _, placeHolderAddress := cltest.MustInsertRandomKey(t, keyStore.Eth()) @@ -121,8 +121,9 @@ func TestRunner(t *testing.T) { // Need a job in order to create a run jb := MakeVoterTurnoutOCRJobSpecWithHTTPURL(t, transmitterAddress, httpURL, bridgeVT.Name.String(), bridgeER.Name.String()) - require.NoError(t, jobORM.CreateJob(jb)) + require.NoError(t, jobORM.CreateJob(testutils.Context(t), jb)) require.NotNil(t, jb.PipelineSpec) + require.NotZero(t, jb.PipelineSpec.JobID) m, err := bridges.MarshalBridgeMetaData(big.NewInt(10), big.NewInt(100)) require.NoError(t, err) @@ -169,6 +170,7 @@ func TestRunner(t *testing.T) { }) t.Run("must delete job before deleting bridge", func(t *testing.T) { + ctx := testutils.Context(t) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) jb := makeOCRJobSpecFromToml(t, fmt.Sprintf(` type = "offchainreporting" @@ -178,20 +180,21 @@ func TestRunner(t *testing.T) { ds1 [type=bridge name="%s"]; """ `, bridge.Name.String())) - require.NoError(t, jobORM.CreateJob(jb)) + require.NoError(t, jobORM.CreateJob(ctx, jb)) // Should not be able to delete a bridge in use. - jids, err := jobORM.FindJobIDsWithBridge(bridge.Name.String()) + jids, err := jobORM.FindJobIDsWithBridge(ctx, bridge.Name.String()) require.NoError(t, err) require.Equal(t, 1, len(jids)) // But if we delete the job, then we can. - require.NoError(t, jobORM.DeleteJob(jb.ID)) - jids, err = jobORM.FindJobIDsWithBridge(bridge.Name.String()) + require.NoError(t, jobORM.DeleteJob(ctx, jb.ID)) + jids, err = jobORM.FindJobIDsWithBridge(ctx, bridge.Name.String()) require.NoError(t, err) require.Equal(t, 0, len(jids)) }) t.Run("referencing a non-existent bridge should error", func(t *testing.T) { + ctx := testutils.Context(t) // Create a random bridge name _, b := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) @@ -223,7 +226,7 @@ func TestRunner(t *testing.T) { `, placeHolderAddress.String())) require.NoError(t, err) // Should error creating it - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(ctx, &jb) require.Error(t, err) assert.Contains(t, err.Error(), "not all bridges exist") @@ -258,7 +261,7 @@ answer1 [type=median index=0]; `, placeHolderAddress.String(), b.Name.String()), nil) require.NoError(t, err) // Should error creating it because of the juels per fee coin non-existent bridge - err = jobORM.CreateJob(&jb2) + err = jobORM.CreateJob(ctx, &jb2) require.Error(t, err) assert.Contains(t, err.Error(), "not all bridges exist") @@ -297,11 +300,12 @@ answer1 [type=median index=0]; `, placeHolderAddress, b.Name.String(), b.Name.String(), b.Name.String()), nil) require.NoError(t, err) // Should not error with duplicate bridges - err = jobORM.CreateJob(&jb3) + err = jobORM.CreateJob(ctx, &jb3) require.NoError(t, err) }) t.Run("handles the case where the parsed value is literally null", func(t *testing.T) { + ctx := testutils.Context(t) var httpURL string resp := `{"USD": null}` { @@ -311,7 +315,7 @@ answer1 [type=median index=0]; // Need a job in order to create a run jb := makeSimpleFetchOCRJobSpecWithHTTPURL(t, transmitterAddress, httpURL, false) - err := jobORM.CreateJob(jb) + err := jobORM.CreateJob(ctx, jb) require.NoError(t, err) runID, taskResults, err := runner.ExecuteAndInsertFinishedRun(testutils.Context(t), *jb.PipelineSpec, pipeline.NewVarsFrom(nil), logger.TestLogger(t), true) @@ -357,7 +361,7 @@ answer1 [type=median index=0]; // Need a job in order to create a run jb := makeSimpleFetchOCRJobSpecWithHTTPURL(t, transmitterAddress, httpURL, false) - err := jobORM.CreateJob(jb) + err := jobORM.CreateJob(testutils.Context(t), jb) require.NoError(t, err) runID, taskResults, err := runner.ExecuteAndInsertFinishedRun(testutils.Context(t), *jb.PipelineSpec, pipeline.NewVarsFrom(nil), logger.TestLogger(t), true) @@ -402,7 +406,7 @@ answer1 [type=median index=0]; // Need a job in order to create a run jb := makeSimpleFetchOCRJobSpecWithHTTPURL(t, transmitterAddress, httpURL, true) - err := jobORM.CreateJob(jb) + err := jobORM.CreateJob(testutils.Context(t), jb) require.NoError(t, err) runID, taskResults, err := runner.ExecuteAndInsertFinishedRun(testutils.Context(t), *jb.PipelineSpec, pipeline.NewVarsFrom(nil), logger.TestLogger(t), true) @@ -451,13 +455,13 @@ answer1 [type=median index=0]; err = toml.Unmarshal([]byte(s), &jb) require.NoError(t, err) jb.MaxTaskDuration = models.Interval(cltest.MustParseDuration(t, "1s")) - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) lggr := logger.TestLogger(t) _, err = keyStore.P2P().Create(ctx) assert.NoError(t, err) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), config.Database(), db, lggr) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), db, lggr) servicetest.Run(t, pw) sd := ocr.NewDelegate( db, @@ -487,12 +491,12 @@ answer1 [type=median index=0]; require.NoError(t, err) jb.MaxTaskDuration = models.Interval(cltest.MustParseDuration(t, "1s")) - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) assert.Equal(t, jb.MaxTaskDuration, models.Interval(cltest.MustParseDuration(t, "1s"))) lggr := logger.TestLogger(t) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), config.Database(), db, lggr) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), db, lggr) servicetest.Run(t, pw) sd := ocr.NewDelegate( db, @@ -516,11 +520,11 @@ answer1 [type=median index=0]; require.NoError(t, err) err = toml.Unmarshal([]byte(s), &jb) require.NoError(t, err) - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) lggr := logger.TestLogger(t) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), config.Database(), db, lggr) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), db, lggr) servicetest.Run(t, pw) sd := ocr.NewDelegate( db, @@ -571,12 +575,12 @@ answer1 [type=median index=0]; require.NoError(t, err) jb.MaxTaskDuration = models.Interval(cltest.MustParseDuration(t, "1s")) - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(testutils.Context(t), &jb) require.NoError(t, err) assert.Equal(t, jb.MaxTaskDuration, models.Interval(cltest.MustParseDuration(t, "1s"))) lggr := logger.TestLogger(t) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), config.Database(), db, lggr) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), db, lggr) servicetest.Run(t, pw) sd := ocr.NewDelegate( db, @@ -617,11 +621,11 @@ answer1 [type=median index=0]; jb := makeOCRJobSpecFromToml(t, spec) // Create an OCR job - err = jobORM.CreateJob(jb) + err = jobORM.CreateJob(ctx, jb) require.NoError(t, err) lggr := logger.TestLogger(t) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), config.Database(), db, lggr) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), db, lggr) servicetest.Run(t, pw) sd := ocr.NewDelegate( db, @@ -640,6 +644,7 @@ answer1 [type=median index=0]; // Return an error getting the contract code. ethClient.On("CodeAt", mock.Anything, mock.Anything, mock.Anything).Return(nil, errors.New("no such code")) + for _, s := range services { err = s.Start(ctx) require.NoError(t, err) @@ -659,7 +664,7 @@ answer1 [type=median index=0]; } // Ensure we can delete an errored - err = jobORM.DeleteJob(jb.ID) + err = jobORM.DeleteJob(ctx, jb.ID) require.NoError(t, err) se = []job.SpecError{} err = db.Select(&se, `SELECT * FROM job_spec_errors`) @@ -675,6 +680,7 @@ answer1 [type=median index=0]; }) t.Run("timeouts", func(t *testing.T) { + ctx := testutils.Context(t) // There are 4 timeouts: // - ObservationTimeout = how long the whole OCR time needs to run, or it fails (default 10 seconds) // - config.JobPipelineMaxTaskDuration() = node level maximum time for a pipeline task (default 10 minutes) @@ -689,7 +695,7 @@ answer1 [type=median index=0]; defer serv.Close() jb := makeMinimalHTTPOracleSpec(t, db, config, cltest.NewEIP55Address().String(), transmitterAddress.Hex(), cltest.DefaultOCRKeyBundleID, serv.URL, `timeout="1ns"`) - err := jobORM.CreateJob(jb) + err := jobORM.CreateJob(ctx, jb) require.NoError(t, err) _, taskResults, err := runner.ExecuteAndInsertFinishedRun(testutils.Context(t), *jb.PipelineSpec, pipeline.NewVarsFrom(nil), logger.TestLogger(t), true) @@ -700,7 +706,7 @@ answer1 [type=median index=0]; // No task timeout should succeed. jb = makeMinimalHTTPOracleSpec(t, db, config, cltest.NewEIP55Address().String(), transmitterAddress.Hex(), cltest.DefaultOCRKeyBundleID, serv.URL, "") jb.Name = null.NewString("a job 2", true) - err = jobORM.CreateJob(jb) + err = jobORM.CreateJob(ctx, jb) require.NoError(t, err) _, taskResults, err = runner.ExecuteAndInsertFinishedRun(testutils.Context(t), *jb.PipelineSpec, pipeline.NewVarsFrom(nil), logger.TestLogger(t), true) require.NoError(t, err) @@ -712,7 +718,7 @@ answer1 [type=median index=0]; jb = makeMinimalHTTPOracleSpec(t, db, config, cltest.NewEIP55Address().String(), transmitterAddress.Hex(), cltest.DefaultOCRKeyBundleID, serv.URL, "") jb.MaxTaskDuration = models.Interval(time.Duration(1)) jb.Name = null.NewString("a job 3", true) - err = jobORM.CreateJob(jb) + err = jobORM.CreateJob(ctx, jb) require.NoError(t, err) _, taskResults, err = runner.ExecuteAndInsertFinishedRun(testutils.Context(t), *jb.PipelineSpec, pipeline.NewVarsFrom(nil), logger.TestLogger(t), true) @@ -722,6 +728,7 @@ answer1 [type=median index=0]; }) t.Run("deleting jobs", func(t *testing.T) { + ctx := testutils.Context(t) var httpURL string { resp := `{"USD": 42.42}` @@ -731,7 +738,7 @@ answer1 [type=median index=0]; // Need a job in order to create a run jb := makeSimpleFetchOCRJobSpecWithHTTPURL(t, transmitterAddress, httpURL, false) - err := jobORM.CreateJob(jb) + err := jobORM.CreateJob(ctx, jb) require.NoError(t, err) _, taskResults, err := runner.ExecuteAndInsertFinishedRun(testutils.Context(t), *jb.PipelineSpec, pipeline.NewVarsFrom(nil), logger.TestLogger(t), true) @@ -742,7 +749,7 @@ answer1 [type=median index=0]; assert.Equal(t, "4242", results.Values[0].(decimal.Decimal).String()) // Delete the job - err = jobORM.DeleteJob(jb.ID) + err = jobORM.DeleteJob(ctx, jb.ID) require.NoError(t, err) // Create another run, it should fail @@ -849,7 +856,7 @@ func TestRunner_Success_Callback_AsyncJob(t *testing.T) { require.NoError(t, err) bridgeCalled <- struct{}{} })) - _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{URL: bridgeServer.URL}) + _, bridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{URL: bridgeServer.URL}) bridgeName = bridge.Name.String() defer bridgeServer.Close() } @@ -879,7 +886,7 @@ func TestRunner_Success_Callback_AsyncJob(t *testing.T) { """ `, jobUUID, eiName, cltest.MustJSONMarshal(t, eiSpec), bridgeName) - _, err := webhook.ValidatedWebhookSpec(tomlSpec, app.GetExternalInitiatorManager()) + _, err := webhook.ValidatedWebhookSpec(testutils.Context(t), tomlSpec, app.GetExternalInitiatorManager()) require.NoError(t, err) job := cltest.CreateJobViaWeb(t, app, []byte(cltest.MustJSONMarshal(t, web.CreateJobRequest{TOML: tomlSpec}))) jobID = job.ID @@ -891,9 +898,9 @@ func TestRunner_Success_Callback_AsyncJob(t *testing.T) { _ = cltest.CreateJobRunViaExternalInitiatorV2(t, app, jobUUID, *eia, cltest.MustJSONMarshal(t, eiRequest)) - pipelineORM := pipeline.NewORM(app.GetSqlxDB(), logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - bridgesORM := bridges.NewORM(app.GetSqlxDB()) - jobORM := NewTestORM(t, app.GetSqlxDB(), pipelineORM, bridgesORM, app.KeyStore, cfg.Database()) + pipelineORM := pipeline.NewORM(app.GetDB(), logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) + bridgesORM := bridges.NewORM(app.GetDB()) + jobORM := NewTestORM(t, app.GetDB(), pipelineORM, bridgesORM, app.KeyStore) // Trigger v2/resume select { @@ -1028,7 +1035,7 @@ func TestRunner_Error_Callback_AsyncJob(t *testing.T) { require.NoError(t, err) bridgeCalled <- struct{}{} })) - _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{URL: bridgeServer.URL}) + _, bridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{URL: bridgeServer.URL}) bridgeName = bridge.Name.String() defer bridgeServer.Close() } @@ -1058,19 +1065,20 @@ func TestRunner_Error_Callback_AsyncJob(t *testing.T) { """ `, jobUUID, eiName, cltest.MustJSONMarshal(t, eiSpec), bridgeName) - _, err := webhook.ValidatedWebhookSpec(tomlSpec, app.GetExternalInitiatorManager()) + _, err := webhook.ValidatedWebhookSpec(testutils.Context(t), tomlSpec, app.GetExternalInitiatorManager()) require.NoError(t, err) job := cltest.CreateJobViaWeb(t, app, []byte(cltest.MustJSONMarshal(t, web.CreateJobRequest{TOML: tomlSpec}))) jobID = job.ID require.Eventually(t, func() bool { return eiNotifiedOfCreate }, 5*time.Second, 10*time.Millisecond, "expected external initiator to be notified of new job") } + t.Run("simulate request from EI -> Core node with erroring callback", func(t *testing.T) { _ = cltest.CreateJobRunViaExternalInitiatorV2(t, app, jobUUID, *eia, cltest.MustJSONMarshal(t, eiRequest)) - pipelineORM := pipeline.NewORM(app.GetSqlxDB(), logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - bridgesORM := bridges.NewORM(app.GetSqlxDB()) - jobORM := NewTestORM(t, app.GetSqlxDB(), pipelineORM, bridgesORM, app.KeyStore, cfg.Database()) + pipelineORM := pipeline.NewORM(app.GetDB(), logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) + bridgesORM := bridges.NewORM(app.GetDB()) + jobORM := NewTestORM(t, app.GetDB(), pipelineORM, bridgesORM, app.KeyStore) // Trigger v2/resume select { diff --git a/core/services/job/spawner.go b/core/services/job/spawner.go index 8024424226c..6bb2cdbf76b 100644 --- a/core/services/job/spawner.go +++ b/core/services/job/spawner.go @@ -9,13 +9,11 @@ import ( pkgerrors "github.com/pkg/errors" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) //go:generate mockery --quiet --name Spawner --output ./mocks/ --case=underscore @@ -29,16 +27,16 @@ type ( // CreateJob creates a new job and starts services. // All services must start without errors for the job to be active. - CreateJob(jb *Job, qopts ...pg.QOpt) (err error) + CreateJob(ctx context.Context, ds sqlutil.DataSource, jb *Job) (err error) // DeleteJob deletes a job and stops any active services. - DeleteJob(jobID int32, qopts ...pg.QOpt) error + DeleteJob(ctx context.Context, ds sqlutil.DataSource, jobID int32) error // ActiveJobs returns a map of jobs with active services (started without error). ActiveJobs() map[int32]Job // StartService starts services for the given job spec. // NOTE: Prefer to use CreateJob, this is only publicly exposed for use in tests // to start a job that was previously manually inserted into DB - StartService(ctx context.Context, spec Job, qopts ...pg.QOpt) error + StartService(ctx context.Context, spec Job) error } Checker interface { @@ -54,7 +52,6 @@ type ( jobTypeDelegates map[Type]Delegate activeJobs map[int32]activeJob activeJobsMu sync.RWMutex - q pg.Q lggr logger.Logger chStop services.StopChan @@ -90,14 +87,13 @@ type ( var _ Spawner = (*spawner)(nil) -func NewSpawner(orm ORM, config Config, checker Checker, jobTypeDelegates map[Type]Delegate, db *sqlx.DB, lggr logger.Logger, lbDependentAwaiters []utils.DependentAwaiter) *spawner { +func NewSpawner(orm ORM, config Config, checker Checker, jobTypeDelegates map[Type]Delegate, lggr logger.Logger, lbDependentAwaiters []utils.DependentAwaiter) *spawner { namedLogger := lggr.Named("JobSpawner") s := &spawner{ orm: orm, config: config, checker: checker, jobTypeDelegates: jobTypeDelegates, - q: pg.NewQ(db, namedLogger, config), lggr: namedLogger, activeJobs: make(map[int32]activeJob), chStop: make(services.StopChan), @@ -134,7 +130,7 @@ func (js *spawner) HealthReport() map[string]error { func (js *spawner) startAllServices(ctx context.Context) { // TODO: rename to find AllJobs - specs, _, err := js.orm.FindJobs(0, math.MaxUint32) + specs, _, err := js.orm.FindJobs(ctx, 0, math.MaxUint32) if err != nil { werr := fmt.Errorf("couldn't fetch unclaimed jobs: %v", err) js.lggr.Critical(werr.Error()) @@ -191,7 +187,7 @@ func (js *spawner) stopService(jobID int32) { delete(js.activeJobs, jobID) } -func (js *spawner) StartService(ctx context.Context, jb Job, qopts ...pg.QOpt) error { +func (js *spawner) StartService(ctx context.Context, jb Job) error { lggr := js.lggr.With("jobID", jb.ID) js.activeJobsMu.Lock() defer js.activeJobsMu.Unlock() @@ -220,7 +216,7 @@ func (js *spawner) StartService(ctx context.Context, jb Job, qopts ...pg.QOpt) e lggr.Errorw("Error creating services for job", "err", err) cctx, cancel := js.chStop.NewCtx() defer cancel() - js.orm.TryRecordError(jb.ID, err.Error(), pg.WithParentCtx(cctx)) + js.orm.TryRecordError(cctx, jb.ID, err.Error()) js.activeJobs[jb.ID] = aj return pkgerrors.Wrapf(err, "failed to create services for job: %d", jb.ID) } @@ -249,7 +245,11 @@ func (js *spawner) StartService(ctx context.Context, jb Job, qopts ...pg.QOpt) e } // Should not get called before Start() -func (js *spawner) CreateJob(jb *Job, qopts ...pg.QOpt) (err error) { +func (js *spawner) CreateJob(ctx context.Context, ds sqlutil.DataSource, jb *Job) (err error) { + orm := js.orm + if ds != nil { + orm = orm.WithDataSource(ds) + } delegate, exists := js.jobTypeDelegates[jb.Type] if !exists { js.lggr.Errorf("job type '%s' has not been registered with the job.Spawner", jb.Type) @@ -257,15 +257,7 @@ func (js *spawner) CreateJob(jb *Job, qopts ...pg.QOpt) (err error) { return } - q := js.q.WithOpts(qopts...) - pctx, cancel := js.chStop.Ctx(q.ParentCtx) - defer cancel() - q.ParentCtx = pctx - - ctx, cancel := q.Context() - defer cancel() - - err = js.orm.CreateJob(jb, pg.WithQueryer(q.Queryer), pg.WithParentCtx(ctx)) + err = orm.CreateJob(ctx, jb) if err != nil { js.lggr.Errorw("Error creating job", "type", jb.Type, "err", err) return @@ -273,7 +265,7 @@ func (js *spawner) CreateJob(jb *Job, qopts ...pg.QOpt) (err error) { js.lggr.Infow("Created job", "type", jb.Type, "jobID", jb.ID) delegate.BeforeJobCreated(*jb) - err = js.StartService(pctx, *jb, pg.WithQueryer(q.Queryer)) + err = js.StartService(ctx, *jb) if err != nil { js.lggr.Errorw("Error starting job services", "type", jb.Type, "jobID", jb.ID, "err", err) } else { @@ -286,7 +278,10 @@ func (js *spawner) CreateJob(jb *Job, qopts ...pg.QOpt) (err error) { } // Should not get called before Start() -func (js *spawner) DeleteJob(jobID int32, qopts ...pg.QOpt) error { +func (js *spawner) DeleteJob(ctx context.Context, ds sqlutil.DataSource, jobID int32) error { + if ds == nil { + ds = js.orm.DataSource() + } if jobID == 0 { return pkgerrors.New("will not delete job with 0 ID") } @@ -302,15 +297,8 @@ func (js *spawner) DeleteJob(jobID int32, qopts ...pg.QOpt) error { aj, exists = js.activeJobs[jobID] }() - q := js.q.WithOpts(qopts...) - pctx, cancel := js.chStop.Ctx(q.ParentCtx) - defer cancel() - q.ParentCtx = pctx - ctx, cancel := q.Context() - defer cancel() - if !exists { // inactive, so look up the spec and delegate - jb, err := js.orm.FindJob(ctx, jobID) + jb, err := js.orm.WithDataSource(ds).FindJob(ctx, jobID) if err != nil { return pkgerrors.Wrapf(err, "job %d not found", jobID) } @@ -330,8 +318,8 @@ func (js *spawner) DeleteJob(jobID int32, qopts ...pg.QOpt) error { aj.delegate.BeforeJobDeleted(aj.spec) lggr.Debugw("Callback: BeforeDeleteJob done") - err := q.Transaction(func(tx pg.Queryer) error { - err := js.orm.DeleteJob(jobID, pg.WithQueryer(tx)) + err := sqlutil.Transact(ctx, js.orm.WithDataSource, ds, nil, func(tx ORM) error { + err := tx.DeleteJob(ctx, jobID) if err != nil { js.lggr.Errorw("Error deleting job", "jobID", jobID, "err", err) return err diff --git a/core/services/job/spawner_test.go b/core/services/job/spawner_test.go index ae8ffaa2161..7b4ab138e7c 100644 --- a/core/services/job/spawner_test.go +++ b/core/services/job/spawner_test.go @@ -101,10 +101,10 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) t.Run("should respect its dependents", func(t *testing.T) { lggr := logger.TestLogger(t) - orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore, config.Database()) + orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore) a := utils.NewDependentAwaiter() a.AddDependents(1) - spawner := job.NewSpawner(orm, config.Database(), noopChecker{}, map[job.Type]job.Delegate{}, db, lggr, []utils.DependentAwaiter{a}) + spawner := job.NewSpawner(orm, config.Database(), noopChecker{}, map[job.Type]job.Delegate{}, lggr, []utils.DependentAwaiter{a}) // Starting the spawner should signal to the dependents result := make(chan bool) go func() { @@ -124,7 +124,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { jobB := makeOCRJobSpec(t, address, bridge.Name.String(), bridge2.Name.String()) lggr := logger.TestLogger(t) - orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore, config.Database()) + orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore) eventuallyA := cltest.NewAwaiter() serviceA1 := mocks.NewServiceCtx(t) @@ -146,9 +146,10 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { spawner := job.NewSpawner(orm, config.Database(), noopChecker{}, map[job.Type]job.Delegate{ jobA.Type: delegateA, jobB.Type: delegateB, - }, db, lggr, nil) - require.NoError(t, spawner.Start(testutils.Context(t))) - err := spawner.CreateJob(jobA) + }, lggr, nil) + ctx := testutils.Context(t) + require.NoError(t, spawner.Start(ctx)) + err := spawner.CreateJob(ctx, nil, jobA) require.NoError(t, err) jobSpecIDA := jobA.ID delegateA.jobID = jobSpecIDA @@ -156,7 +157,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { eventuallyA.AwaitOrFail(t, 20*time.Second) - err = spawner.CreateJob(jobB) + err = spawner.CreateJob(ctx, nil, jobB) require.NoError(t, err) jobSpecIDB := jobB.ID delegateB.jobID = jobSpecIDB @@ -166,12 +167,12 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { serviceA1.On("Close").Return(nil).Once() serviceA2.On("Close").Return(nil).Once() - err = spawner.DeleteJob(jobSpecIDA) + err = spawner.DeleteJob(ctx, nil, jobSpecIDA) require.NoError(t, err) serviceB1.On("Close").Return(nil).Once() serviceB2.On("Close").Return(nil).Once() - err = spawner.DeleteJob(jobSpecIDB) + err = spawner.DeleteJob(ctx, nil, jobSpecIDB) require.NoError(t, err) require.NoError(t, spawner.Close()) @@ -189,19 +190,20 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { serviceA2.On("Start", mock.Anything).Return(nil).Once().Run(func(mock.Arguments) { eventually.ItHappened() }) lggr := logger.TestLogger(t) - orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore, config.Database()) + orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore) mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) d := ocr.NewDelegate(nil, orm, nil, nil, nil, monitoringEndpoint, legacyChains, logger.TestLogger(t), config, mailMon) delegateA := &delegate{jobA.Type, []job.ServiceCtx{serviceA1, serviceA2}, 0, nil, d} spawner := job.NewSpawner(orm, config.Database(), noopChecker{}, map[job.Type]job.Delegate{ jobA.Type: delegateA, - }, db, lggr, nil) + }, lggr, nil) - err := orm.CreateJob(jobA) + ctx := testutils.Context(t) + err := orm.CreateJob(ctx, jobA) require.NoError(t, err) delegateA.jobID = jobA.ID - require.NoError(t, spawner.Start(testutils.Context(t))) + require.NoError(t, spawner.Start(ctx)) eventually.AwaitOrFail(t) @@ -223,20 +225,21 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { serviceA2.On("Start", mock.Anything).Return(nil).Once().Run(func(mock.Arguments) { eventuallyStart.ItHappened() }) lggr := logger.TestLogger(t) - orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore, config.Database()) + orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore) mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) d := ocr.NewDelegate(nil, orm, nil, nil, nil, monitoringEndpoint, legacyChains, logger.TestLogger(t), config, mailMon) delegateA := &delegate{jobA.Type, []job.ServiceCtx{serviceA1, serviceA2}, 0, nil, d} spawner := job.NewSpawner(orm, config.Database(), noopChecker{}, map[job.Type]job.Delegate{ jobA.Type: delegateA, - }, db, lggr, nil) + }, lggr, nil) - err := orm.CreateJob(jobA) + ctx := testutils.Context(t) + err := orm.CreateJob(ctx, jobA) require.NoError(t, err) jobSpecIDA := jobA.ID delegateA.jobID = jobSpecIDA - require.NoError(t, spawner.Start(testutils.Context(t))) + require.NoError(t, spawner.Start(ctx)) defer func() { assert.NoError(t, spawner.Close()) }() eventuallyStart.AwaitOrFail(t) @@ -252,7 +255,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { serviceA1.On("Close").Return(nil).Once() serviceA2.On("Close").Return(nil).Once().Run(func(mock.Arguments) { eventuallyClose.ItHappened() }) - err = spawner.DeleteJob(jobSpecIDA) + err = spawner.DeleteJob(ctx, nil, jobSpecIDA) require.NoError(t, err) eventuallyClose.AwaitOrFail(t) @@ -287,9 +290,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { chain := evmtest.MustGetDefaultChain(t, legacyChains) evmRelayer, err := evmrelayer.NewRelayer(lggr, chain, evmrelayer.RelayerOpts{ - DB: db, DS: db, - QConfig: testopts.GeneralConfig.Database(), CSAETHKeystore: keyStore, }) assert.NoError(t, err) @@ -299,23 +300,24 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { r: evmRelayer, } - jobOCR2VRF := makeOCR2VRFJobSpec(t, keyStore, config, address, chain.ID(), 2) + jobOCR2VRF := makeOCR2VRFJobSpec(t, keyStore, address, chain.ID(), 2) - orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore, config.Database()) + orm := NewTestORM(t, db, pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()), bridges.NewORM(db), keyStore) mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) processConfig := plugins.NewRegistrarConfig(loop.GRPCOpts{}, func(name string) (*plugins.RegisteredLoop, error) { return nil, nil }, func(loopId string) {}) - ocr2DelegateConfig := ocr2.NewDelegateConfig(config.OCR2(), config.Mercury(), config.Threshold(), config.Insecure(), config.JobPipeline(), config.Database(), processConfig) + ocr2DelegateConfig := ocr2.NewDelegateConfig(config.OCR2(), config.Mercury(), config.Threshold(), config.Insecure(), config.JobPipeline(), processConfig) - d := ocr2.NewDelegate(nil, nil, orm, nil, nil, nil, nil, nil, monitoringEndpoint, legacyChains, lggr, ocr2DelegateConfig, + d := ocr2.NewDelegate(nil, orm, nil, nil, nil, nil, nil, monitoringEndpoint, legacyChains, lggr, ocr2DelegateConfig, keyStore.OCR2(), keyStore.DKGSign(), keyStore.DKGEncrypt(), ethKeyStore, testRelayGetter, mailMon, capabilities.NewRegistry(lggr)) delegateOCR2 := &delegate{jobOCR2VRF.Type, []job.ServiceCtx{}, 0, nil, d} spawner := job.NewSpawner(orm, config.Database(), noopChecker{}, map[job.Type]job.Delegate{ jobOCR2VRF.Type: delegateOCR2, - }, db, lggr, nil) + }, lggr, nil) - err = spawner.CreateJob(jobOCR2VRF) + ctx := testutils.Context(t) + err = spawner.CreateJob(ctx, nil, jobOCR2VRF) require.NoError(t, err) jobSpecID := jobOCR2VRF.ID delegateOCR2.jobID = jobOCR2VRF.ID @@ -324,7 +326,7 @@ func TestSpawner_CreateJobDeleteJob(t *testing.T) { lggr.Debugf("Got here, with args %v", args) }) - err = spawner.DeleteJob(jobSpecID) + err = spawner.DeleteJob(ctx, nil, jobSpecID) require.NoError(t, err) lp.AssertNumberOfCalls(t, "UnregisterFilter", 3) diff --git a/core/services/keeper/delegate.go b/core/services/keeper/delegate.go index 184a61e1e1a..71a0c5c43a9 100644 --- a/core/services/keeper/delegate.go +++ b/core/services/keeper/delegate.go @@ -5,8 +5,7 @@ import ( "github.com/pkg/errors" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/config" @@ -25,7 +24,7 @@ type DelegateConfig interface { type Delegate struct { cfg DelegateConfig logger logger.Logger - db *sqlx.DB + ds sqlutil.DataSource jrm job.ORM pr pipeline.Runner legacyChains legacyevm.LegacyChainContainer @@ -35,7 +34,7 @@ type Delegate struct { // NewDelegate is the constructor of Delegate func NewDelegate( cfg DelegateConfig, - db *sqlx.DB, + ds sqlutil.DataSource, jrm job.ORM, pr pipeline.Runner, logger logger.Logger, @@ -45,7 +44,7 @@ func NewDelegate( return &Delegate{ cfg: cfg, logger: logger, - db: db, + ds: ds, jrm: jrm, pr: pr, legacyChains: legacyChains, @@ -58,10 +57,10 @@ func (d *Delegate) JobType() job.Type { return job.Keeper } -func (d *Delegate) BeforeJobCreated(spec job.Job) {} -func (d *Delegate) AfterJobCreated(spec job.Job) {} -func (d *Delegate) BeforeJobDeleted(spec job.Job) {} -func (d *Delegate) OnDeleteJob(context.Context, job.Job) error { return nil } +func (d *Delegate) BeforeJobCreated(spec job.Job) {} +func (d *Delegate) AfterJobCreated(spec job.Job) {} +func (d *Delegate) BeforeJobDeleted(spec job.Job) {} +func (d *Delegate) OnDeleteJob(ctx context.Context, spec job.Job) error { return nil } // ServicesForSpec satisfies the job.Delegate interface. func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services []job.ServiceCtx, err error) { @@ -73,7 +72,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services return nil, err } registryAddress := spec.KeeperSpec.ContractAddress - orm := NewORM(d.db, d.logger) + orm := NewORM(d.ds, d.logger) svcLogger := d.logger.With( "jobID", spec.ID, "registryAddress", registryAddress.Hex(), diff --git a/core/services/keeper/helpers_test.go b/core/services/keeper/helpers_test.go index 3fb9d7760a4..a10c3a48aff 100644 --- a/core/services/keeper/helpers_test.go +++ b/core/services/keeper/helpers_test.go @@ -12,6 +12,10 @@ func (rs *RegistrySynchronizer) ExportedFullSync(ctx context.Context) { rs.fullSync(ctx) } +func (rs *RegistrySynchronizer) ExportedProcessLogs(ctx context.Context) { + rs.processLogs(ctx) +} + func (rw *RegistryWrapper) GetUpkeepIdFromRawRegistrationLog(rawLog types.Log) (*big.Int, error) { switch rw.Version { case RegistryVersion_1_0, RegistryVersion_1_1: diff --git a/core/services/keeper/integration_test.go b/core/services/keeper/integration_test.go index 08699d3d835..9e4cf5f9041 100644 --- a/core/services/keeper/integration_test.go +++ b/core/services/keeper/integration_test.go @@ -284,7 +284,7 @@ func TestKeeperEthIntegration(t *testing.T) { require.NoError(t, err) backend.Commit() - cltest.WaitForCount(t, app.GetSqlxDB(), "upkeep_registrations", 0) + cltest.WaitForCount(t, app.GetDB(), "upkeep_registrations", 0) // add new upkeep (same target contract) registrationTx, err = registryWrapper.RegisterUpkeep(steve, upkeepAddr, 2_500_000, carrol.From, []byte{}) @@ -308,8 +308,8 @@ func TestKeeperEthIntegration(t *testing.T) { require.NoError(t, err) var registry keeper.Registry - require.NoError(t, app.GetSqlxDB().Get(®istry, `SELECT * FROM keeper_registries`)) - cltest.AssertRecordEventually(t, app.GetSqlxDB(), ®istry, fmt.Sprintf("SELECT * FROM keeper_registries WHERE id = %d", registry.ID), func() bool { + require.NoError(t, app.GetDB().GetContext(ctx, ®istry, `SELECT * FROM keeper_registries`)) + cltest.AssertRecordEventually(t, app.GetDB(), ®istry, fmt.Sprintf("SELECT * FROM keeper_registries WHERE id = %d", registry.ID), func() bool { return registry.KeeperIndex == -1 }) runs, err := app.PipelineORM().GetAllRuns(ctx) @@ -435,7 +435,7 @@ func TestKeeperForwarderEthIntegration(t *testing.T) { SchemaVersion: 1, ForwardingAllowed: true, } - err = app.JobORM().CreateJob(&jb) + err = app.JobORM().CreateJob(testutils.Context(t), &jb) require.NoError(t, err) registry := keeper.Registry{ diff --git a/core/services/keeper/registry_synchronizer_helper_test.go b/core/services/keeper/registry_synchronizer_helper_test.go index 2726c9a754d..73a3cb88166 100644 --- a/core/services/keeper/registry_synchronizer_helper_test.go +++ b/core/services/keeper/registry_synchronizer_helper_test.go @@ -46,7 +46,7 @@ func setupRegistrySync(t *testing.T, version keeper.RegistryVersion) ( j := cltest.MustInsertKeeperJob(t, db, korm, cltest.NewEIP55Address(), cltest.NewEIP55Address()) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, Client: ethClient, LogBroadcaster: lbMock, GeneralConfig: cfg, KeyStore: keyStore.Eth()}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) - jpv2 := cltest.NewJobPipelineV2(t, cfg.WebServer(), cfg.JobPipeline(), cfg.Database(), legacyChains, db, keyStore, nil, nil) + jpv2 := cltest.NewJobPipelineV2(t, cfg.WebServer(), cfg.JobPipeline(), legacyChains, db, keyStore, nil, nil) contractAddress := j.KeeperSpec.ContractAddress.Address() switch version { diff --git a/core/services/keeper/registry_synchronizer_process_logs.go b/core/services/keeper/registry_synchronizer_process_logs.go index a1bdcd8db0b..5aaddb6f1e4 100644 --- a/core/services/keeper/registry_synchronizer_process_logs.go +++ b/core/services/keeper/registry_synchronizer_process_logs.go @@ -82,6 +82,9 @@ func (rs *RegistrySynchronizer) processLogs(ctx context.Context) { } if err != nil { + if ctx.Err() != nil { + return + } rs.logger.Error(err) } diff --git a/core/services/keeper/registry_synchronizer_sync.go b/core/services/keeper/registry_synchronizer_sync.go index 6c0e12d844b..6615d376e2b 100644 --- a/core/services/keeper/registry_synchronizer_sync.go +++ b/core/services/keeper/registry_synchronizer_sync.go @@ -30,7 +30,7 @@ func (rs *RegistrySynchronizer) fullSync(ctx context.Context) { } func (rs *RegistrySynchronizer) syncRegistry(ctx context.Context) (Registry, error) { - registry, err := rs.newRegistryFromChain() + registry, err := rs.newRegistryFromChain(ctx) if err != nil { return Registry{}, errors.Wrap(err, "failed to get new registry from chain") } @@ -138,13 +138,13 @@ func (rs *RegistrySynchronizer) syncUpkeep(ctx context.Context, getter upkeepGet } // newRegistryFromChain returns a Registry struct with fields synched from those on chain -func (rs *RegistrySynchronizer) newRegistryFromChain() (Registry, error) { +func (rs *RegistrySynchronizer) newRegistryFromChain(ctx context.Context) (Registry, error) { fromAddress := rs.effectiveKeeperAddress contractAddress := rs.job.KeeperSpec.ContractAddress registryConfig, err := rs.registryWrapper.GetConfig(nil) if err != nil { - rs.jrm.TryRecordError(rs.job.ID, err.Error()) + rs.jrm.TryRecordError(ctx, rs.job.ID, err.Error()) return Registry{}, errors.Wrap(err, "failed to get contract config") } diff --git a/core/services/keeper/upkeep_executer_test.go b/core/services/keeper/upkeep_executer_test.go index ec23331f904..cd02fc27d11 100644 --- a/core/services/keeper/upkeep_executer_test.go +++ b/core/services/keeper/upkeep_executer_test.go @@ -83,7 +83,7 @@ func setup(t *testing.T, estimator gas.EvmFeeEstimator, overrideFn func(c *chain txm := txmmocks.NewMockEvmTxManager(t) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{TxManager: txm, DB: db, Client: ethClient, KeyStore: keyStore.Eth(), GeneralConfig: cfg, GasEstimator: estimator}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) - jpv2 := cltest.NewJobPipelineV2(t, cfg.WebServer(), cfg.JobPipeline(), cfg.Database(), legacyChains, db, keyStore, nil, nil) + jpv2 := cltest.NewJobPipelineV2(t, cfg.WebServer(), cfg.JobPipeline(), legacyChains, db, keyStore, nil, nil) ch := evmtest.MustGetDefaultChain(t, legacyChains) orm := keeper.NewORM(db, logger.TestLogger(t)) registry, jb := cltest.MustInsertKeeperRegistry(t, db, orm, keyStore.Eth(), 0, 1, 20) diff --git a/core/services/keystore/eth_test.go b/core/services/keystore/eth_test.go index 07a41599f7d..4a9c8a952ff 100644 --- a/core/services/keystore/eth_test.go +++ b/core/services/keystore/eth_test.go @@ -13,8 +13,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -29,9 +27,7 @@ import ( func Test_EthKeyStore(t *testing.T) { t.Parallel() - db := sqlutil.WrapDataSource(pgtest.NewSqlxDB(t), logger.Test(t), sqlutil.TimeoutHook(func() time.Duration { - return 5 * time.Minute - }), sqlutil.MonitorHook(func() bool { return true })) + db := pgtest.NewSqlxDB(t) keyStore := keystore.ExposedNewMaster(t, db) err := keyStore.Unlock(testutils.Context(t), cltest.Password) diff --git a/core/services/llo/delegate.go b/core/services/llo/delegate.go index 2bab0ab12a2..6cdad6290fc 100644 --- a/core/services/llo/delegate.go +++ b/core/services/llo/delegate.go @@ -13,13 +13,13 @@ import ( "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" "github.com/smartcontractkit/chainlink-data-streams/llo" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/llo/evm" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/streams" ) @@ -43,11 +43,11 @@ type delegate struct { } type DelegateConfig struct { - Logger logger.Logger - Queryer pg.Queryer - Runner streams.Runner - Registry Registry - JobName null.String + Logger logger.Logger + DataSource sqlutil.DataSource + Runner streams.Runner + Registry Registry + JobName null.String // LLO ChannelDefinitionCache llotypes.ChannelDefinitionCache @@ -67,8 +67,8 @@ type DelegateConfig struct { } func NewDelegate(cfg DelegateConfig) (job.ServiceCtx, error) { - if cfg.Queryer == nil { - return nil, errors.New("Queryer must not be nil") + if cfg.DataSource == nil { + return nil, errors.New("DataSource must not be nil") } if cfg.Runner == nil { return nil, errors.New("Runner must not be nil") diff --git a/core/services/ocr/contract_tracker.go b/core/services/ocr/contract_tracker.go index 5746f97cd38..f7c7a9940b5 100644 --- a/core/services/ocr/contract_tracker.go +++ b/core/services/ocr/contract_tracker.go @@ -90,8 +90,9 @@ type ( } OCRContractTrackerDB interface { - SaveLatestRoundRequested(ctx context.Context, tx sqlutil.DataSource, rr offchainaggregator.OffchainAggregatorRoundRequested) error + SaveLatestRoundRequested(ctx context.Context, rr offchainaggregator.OffchainAggregatorRoundRequested) error LoadLatestRoundRequested(ctx context.Context) (rr offchainaggregator.OffchainAggregatorRoundRequested, err error) + WithDataSource(sqlutil.DataSource) OCRContractTrackerDB } ) @@ -293,7 +294,7 @@ func (t *OCRContractTracker) HandleLog(ctx context.Context, lb log.Broadcast) { } if IsLaterThan(raw, t.latestRoundRequested.Raw) { err = sqlutil.TransactDataSource(ctx, t.ds, nil, func(tx sqlutil.DataSource) error { - if err = t.ocrDB.SaveLatestRoundRequested(ctx, tx, *rr); err != nil { + if err = t.ocrDB.WithDataSource(tx).SaveLatestRoundRequested(ctx, *rr); err != nil { return err } return t.logBroadcaster.MarkConsumed(ctx, tx, lb) diff --git a/core/services/ocr/contract_tracker_test.go b/core/services/ocr/contract_tracker_test.go index 6f8b05c6436..d8fd8a01a11 100644 --- a/core/services/ocr/contract_tracker_test.go +++ b/core/services/ocr/contract_tracker_test.go @@ -224,9 +224,10 @@ func Test_OCRContractTracker_HandleLog_OCRContractLatestRoundRequested(t *testin uni.lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) uni.lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - uni.db.On("SaveLatestRoundRequested", mock.Anything, mock.Anything, mock.MatchedBy(func(rr offchainaggregator.OffchainAggregatorRoundRequested) bool { + uni.db.On("SaveLatestRoundRequested", mock.Anything, mock.MatchedBy(func(rr offchainaggregator.OffchainAggregatorRoundRequested) bool { return rr.Epoch == 1 && rr.Round == 1 })).Return(nil) + uni.db.On("WithDataSource", mock.Anything).Return(uni.db) uni.tracker.HandleLog(testutils.Context(t), logBroadcast) @@ -244,7 +245,7 @@ func Test_OCRContractTracker_HandleLog_OCRContractLatestRoundRequested(t *testin uni.lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) uni.lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - uni.db.On("SaveLatestRoundRequested", mock.Anything, mock.Anything, mock.MatchedBy(func(rr offchainaggregator.OffchainAggregatorRoundRequested) bool { + uni.db.On("SaveLatestRoundRequested", mock.Anything, mock.MatchedBy(func(rr offchainaggregator.OffchainAggregatorRoundRequested) bool { return rr.Epoch == 1 && rr.Round == 9 })).Return(nil) @@ -273,7 +274,7 @@ func Test_OCRContractTracker_HandleLog_OCRContractLatestRoundRequested(t *testin uni.lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) uni.lb.On("MarkConsumed", mock.Anything, mock.Anything, mock.Anything).Return(nil) - uni.db.On("SaveLatestRoundRequested", mock.Anything, mock.Anything, mock.MatchedBy(func(rr offchainaggregator.OffchainAggregatorRoundRequested) bool { + uni.db.On("SaveLatestRoundRequested", mock.Anything, mock.MatchedBy(func(rr offchainaggregator.OffchainAggregatorRoundRequested) bool { return rr.Epoch == 2 && rr.Round == 1 })).Return(nil) @@ -295,7 +296,8 @@ func Test_OCRContractTracker_HandleLog_OCRContractLatestRoundRequested(t *testin logBroadcast.On("String").Return("").Maybe() uni.lb.On("WasAlreadyConsumed", mock.Anything, mock.Anything).Return(false, nil) - uni.db.On("SaveLatestRoundRequested", mock.Anything, mock.Anything, mock.Anything).Return(errors.New("something exploded")) + uni.db.On("SaveLatestRoundRequested", mock.Anything, mock.Anything).Return(errors.New("something exploded")) + uni.db.On("WithDataSource", mock.Anything).Return(uni.db) uni.tracker.HandleLog(testutils.Context(t), logBroadcast) diff --git a/core/services/ocr/database.go b/core/services/ocr/database.go index 95993de9d5c..b5f890565f1 100644 --- a/core/services/ocr/database.go +++ b/core/services/ocr/database.go @@ -38,6 +38,9 @@ func NewDB(ds sqlutil.DataSource, oracleSpecID int32, lggr logger.Logger) *db { lggr: logger.Sugared(lggr), } } +func (d *db) WithDataSource(ds sqlutil.DataSource) OCRContractTrackerDB { + return NewDB(ds, d.oracleSpecID, d.lggr) +} func (d *db) ReadState(ctx context.Context, cd ocrtypes.ConfigDigest) (ps *ocrtypes.PersistentState, err error) { stmt := ` @@ -293,12 +296,12 @@ WHERE ocr_oracle_spec_id = $1 AND time < $2 return } -func (d *db) SaveLatestRoundRequested(ctx context.Context, tx sqlutil.DataSource, rr offchainaggregator.OffchainAggregatorRoundRequested) error { +func (d *db) SaveLatestRoundRequested(ctx context.Context, rr offchainaggregator.OffchainAggregatorRoundRequested) error { rawLog, err := json.Marshal(rr.Raw) if err != nil { return errors.Wrap(err, "could not marshal log as JSON") } - _, err = tx.ExecContext(ctx, ` + _, err = d.ds.ExecContext(ctx, ` INSERT INTO ocr_latest_round_requested (ocr_oracle_spec_id, requester, config_digest, epoch, round, raw) VALUES ($1,$2,$3,$4,$5,$6) ON CONFLICT (ocr_oracle_spec_id) DO UPDATE SET requester = EXCLUDED.requester, diff --git a/core/services/ocr/database_test.go b/core/services/ocr/database_test.go index a2559ca2a87..12f9309450c 100644 --- a/core/services/ocr/database_test.go +++ b/core/services/ocr/database_test.go @@ -407,7 +407,7 @@ func Test_DB_LatestRoundRequested(t *testing.T) { t.Run("saves latest round requested", func(t *testing.T) { ctx := testutils.Context(t) - err := odb.SaveLatestRoundRequested(ctx, sqlDB, rr) + err := odb.SaveLatestRoundRequested(ctx, rr) require.NoError(t, err) rawLog.Index = 42 @@ -421,7 +421,7 @@ func Test_DB_LatestRoundRequested(t *testing.T) { Raw: rawLog, } - err = odb.SaveLatestRoundRequested(ctx, sqlDB, rr) + err = odb.SaveLatestRoundRequested(ctx, rr) require.NoError(t, err) }) diff --git a/core/services/ocr/delegate.go b/core/services/ocr/delegate.go index 88561bd1c3a..690e9ad7c71 100644 --- a/core/services/ocr/delegate.go +++ b/core/services/ocr/delegate.go @@ -10,13 +10,12 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" ocr "github.com/smartcontractkit/libocr/offchainreporting" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types" commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" @@ -35,7 +34,7 @@ import ( ) type Delegate struct { - db *sqlx.DB + ds sqlutil.DataSource jobORM job.ORM keyStore keystore.Master pipelineRunner pipeline.Runner @@ -52,7 +51,7 @@ var _ job.Delegate = (*Delegate)(nil) const ConfigOverriderPollInterval = 30 * time.Second func NewDelegate( - db *sqlx.DB, + ds sqlutil.DataSource, jobORM job.ORM, keyStore keystore.Master, pipelineRunner pipeline.Runner, @@ -64,7 +63,7 @@ func NewDelegate( mailMon *mailbox.Monitor, ) *Delegate { return &Delegate{ - db: db, + ds: ds, jobORM: jobORM, keyStore: keyStore, pipelineRunner: pipelineRunner, @@ -120,7 +119,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) (services [] return nil, errors.Wrap(err, "could not instantiate NewOffchainAggregatorCaller") } - ocrDB := NewDB(d.db, concreteSpec.ID, lggr) + ocrDB := NewDB(d.ds, concreteSpec.ID, lggr) tracker := NewOCRContractTracker( contract, @@ -130,7 +129,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) (services [] chain.LogBroadcaster(), jb.ID, lggr, - d.db, + d.ds, ocrDB, chain.Config().EVM(), chain.HeadBroadcaster(), @@ -157,7 +156,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) (services [] } ocrLogger := commonlogger.NewOCRWrapper(lggr, d.cfg.OCR().TraceLogging(), func(msg string) { - d.jobORM.TryRecordError(jb.ID, msg) + d.jobORM.TryRecordError(ctx, jb.ID, msg) }) lc := toLocalConfig(chain.Config().EVM(), chain.Config().EVM().OCR(), d.cfg.Insecure(), *concreteSpec, d.cfg.OCR()) diff --git a/core/services/ocr/helpers_internal_test.go b/core/services/ocr/helpers_internal_test.go index c6a3d1ac401..a8c656f636c 100644 --- a/core/services/ocr/helpers_internal_test.go +++ b/core/services/ocr/helpers_internal_test.go @@ -3,8 +3,7 @@ package ocr import ( "testing" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -12,6 +11,6 @@ func (c *ConfigOverriderImpl) ExportedUpdateFlagsStatus() error { return c.updateFlagsStatus() } -func NewTestDB(t *testing.T, sqldb *sqlx.DB, oracleSpecID int32) *db { - return NewDB(sqldb, oracleSpecID, logger.TestLogger(t)) +func NewTestDB(t *testing.T, ds sqlutil.DataSource, oracleSpecID int32) *db { + return NewDB(ds, oracleSpecID, logger.TestLogger(t)) } diff --git a/core/services/ocr/mocks/ocr_contract_tracker_db.go b/core/services/ocr/mocks/ocr_contract_tracker_db.go index ed47d87cd1e..d3dcce2641b 100644 --- a/core/services/ocr/mocks/ocr_contract_tracker_db.go +++ b/core/services/ocr/mocks/ocr_contract_tracker_db.go @@ -5,6 +5,7 @@ package mocks import ( context "context" + ocr "github.com/smartcontractkit/chainlink/v2/core/services/ocr" mock "github.com/stretchr/testify/mock" offchainaggregator "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" @@ -45,17 +46,17 @@ func (_m *OCRContractTrackerDB) LoadLatestRoundRequested(ctx context.Context) (o return r0, r1 } -// SaveLatestRoundRequested provides a mock function with given fields: ctx, tx, rr -func (_m *OCRContractTrackerDB) SaveLatestRoundRequested(ctx context.Context, tx sqlutil.DataSource, rr offchainaggregator.OffchainAggregatorRoundRequested) error { - ret := _m.Called(ctx, tx, rr) +// SaveLatestRoundRequested provides a mock function with given fields: ctx, rr +func (_m *OCRContractTrackerDB) SaveLatestRoundRequested(ctx context.Context, rr offchainaggregator.OffchainAggregatorRoundRequested) error { + ret := _m.Called(ctx, rr) if len(ret) == 0 { panic("no return value specified for SaveLatestRoundRequested") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, sqlutil.DataSource, offchainaggregator.OffchainAggregatorRoundRequested) error); ok { - r0 = rf(ctx, tx, rr) + if rf, ok := ret.Get(0).(func(context.Context, offchainaggregator.OffchainAggregatorRoundRequested) error); ok { + r0 = rf(ctx, rr) } else { r0 = ret.Error(0) } @@ -63,6 +64,26 @@ func (_m *OCRContractTrackerDB) SaveLatestRoundRequested(ctx context.Context, tx return r0 } +// WithDataSource provides a mock function with given fields: _a0 +func (_m *OCRContractTrackerDB) WithDataSource(_a0 sqlutil.DataSource) ocr.OCRContractTrackerDB { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for WithDataSource") + } + + var r0 ocr.OCRContractTrackerDB + if rf, ok := ret.Get(0).(func(sqlutil.DataSource) ocr.OCRContractTrackerDB); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(ocr.OCRContractTrackerDB) + } + } + + return r0 +} + // NewOCRContractTrackerDB creates a new instance of OCRContractTrackerDB. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewOCRContractTrackerDB(t interface { diff --git a/core/services/ocr2/database.go b/core/services/ocr2/database.go index 1d449047578..83ee3240a46 100644 --- a/core/services/ocr2/database.go +++ b/core/services/ocr2/database.go @@ -6,18 +6,17 @@ import ( "encoding/binary" "time" - "github.com/jmoiron/sqlx" "github.com/lib/pq" "github.com/pkg/errors" ocrcommon "github.com/smartcontractkit/libocr/commontypes" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) type db struct { - q pg.Q + ds sqlutil.DataSource oracleSpecID int32 pluginID int32 lggr logger.SugaredLogger @@ -28,11 +27,9 @@ var ( ) // NewDB returns a new DB scoped to this oracleSpecID -func NewDB(sqlxDB *sqlx.DB, oracleSpecID int32, pluginID int32, lggr logger.Logger, cfg pg.QConfig) *db { - namedLogger := lggr.Named("OCR2.DB") - +func NewDB(ds sqlutil.DataSource, oracleSpecID int32, pluginID int32, lggr logger.Logger) *db { return &db{ - q: pg.NewQ(sqlxDB, namedLogger, cfg), + ds: ds, oracleSpecID: oracleSpecID, pluginID: pluginID, lggr: logger.Sugared(lggr), @@ -51,7 +48,7 @@ func (d *db) ReadState(ctx context.Context, cd ocrtypes.ConfigDigest) (ps *ocrty var tmp []int64 var highestSentEpochTmp int64 - err = d.q.QueryRowxContext(ctx, stmt, d.oracleSpecID, cd).Scan(&ps.Epoch, &highestSentEpochTmp, pq.Array(&tmp)) + err = d.ds.QueryRowxContext(ctx, stmt, d.oracleSpecID, cd).Scan(&ps.Epoch, &highestSentEpochTmp, pq.Array(&tmp)) if errors.Is(err, sql.ErrNoRows) { return nil, nil } @@ -98,7 +95,9 @@ func (d *db) WriteState(ctx context.Context, cd ocrtypes.ConfigDigest, state ocr NOW() )` - _, err := d.q.WithOpts(pg.WithLongQueryTimeout()).ExecContext( + ctx, cancel := context.WithTimeout(sqlutil.WithoutDefaultTimeout(ctx), time.Minute) + defer cancel() + _, err := d.ds.ExecContext( ctx, stmt, d.oracleSpecID, cd, state.Epoch, state.HighestSentEpoch, pq.Array(&highestReceivedEpoch), ) @@ -126,7 +125,7 @@ func (d *db) ReadConfig(ctx context.Context) (c *ocrtypes.ContractConfig, err er signers := [][]byte{} transmitters := [][]byte{} - err = d.q.QueryRowx(stmt, d.oracleSpecID, d.pluginID).Scan( + err = d.ds.QueryRowxContext(ctx, stmt, d.oracleSpecID, d.pluginID).Scan( &digest, &c.ConfigCount, (*pq.ByteaArray)(&signers), @@ -191,7 +190,7 @@ func (d *db) WriteConfig(ctx context.Context, c ocrtypes.ContractConfig) error { offchain_config = EXCLUDED.offchain_config, updated_at = NOW() ` - _, err := d.q.ExecContext(ctx, stmt, + _, err := d.ds.ExecContext(ctx, stmt, d.oracleSpecID, d.pluginID, c.ConfigDigest, @@ -252,7 +251,7 @@ func (d *db) StorePendingTransmission(ctx context.Context, t ocrtypes.ReportTime updated_at = NOW() ` - _, err := d.q.ExecContext(ctx, stmt, + _, err := d.ds.ExecContext(ctx, stmt, d.oracleSpecID, digest, t.Epoch, @@ -279,7 +278,7 @@ func (d *db) PendingTransmissionsWithConfigDigest(ctx context.Context, cd ocrtyp FROM ocr2_pending_transmissions WHERE ocr2_oracle_spec_id = $1 AND config_digest = $2 ` - rows, err := d.q.QueryxContext(ctx, stmt, d.oracleSpecID, cd) //nolint sqlclosecheck false positive + rows, err := d.ds.QueryxContext(ctx, stmt, d.oracleSpecID, cd) //nolint sqlclosecheck false positive if err != nil { return nil, errors.Wrap(err, "PendingTransmissionsWithConfigDigest failed to query rows") } @@ -325,7 +324,9 @@ func (d *db) PendingTransmissionsWithConfigDigest(ctx context.Context, cd ocrtyp } func (d *db) DeletePendingTransmission(ctx context.Context, t ocrtypes.ReportTimestamp) (err error) { - _, err = d.q.WithOpts(pg.WithLongQueryTimeout()).ExecContext(ctx, ` + ctx, cancel := context.WithTimeout(sqlutil.WithoutDefaultTimeout(ctx), time.Minute) + defer cancel() + _, err = d.ds.ExecContext(ctx, ` DELETE FROM ocr2_pending_transmissions WHERE ocr2_oracle_spec_id = $1 AND config_digest = $2 AND epoch = $3 AND round = $4 `, d.oracleSpecID, t.ConfigDigest, t.Epoch, t.Round) @@ -336,7 +337,9 @@ WHERE ocr2_oracle_spec_id = $1 AND config_digest = $2 AND epoch = $3 AND round } func (d *db) DeletePendingTransmissionsOlderThan(ctx context.Context, t time.Time) (err error) { - _, err = d.q.WithOpts(pg.WithLongQueryTimeout()).ExecContext(ctx, ` + ctx, cancel := context.WithTimeout(sqlutil.WithoutDefaultTimeout(ctx), time.Minute) + defer cancel() + _, err = d.ds.ExecContext(ctx, ` DELETE FROM ocr2_pending_transmissions WHERE ocr2_oracle_spec_id = $1 AND time < $2 `, d.oracleSpecID, t) @@ -347,7 +350,7 @@ WHERE ocr2_oracle_spec_id = $1 AND time < $2 } func (d *db) ReadProtocolState(ctx context.Context, configDigest ocrtypes.ConfigDigest, key string) (value []byte, err error) { - err = d.q.GetContext(ctx, &value, ` + err = d.ds.GetContext(ctx, &value, ` SELECT value FROM ocr_protocol_states WHERE config_digest = $1 AND key = $2; `, configDigest, key) @@ -363,9 +366,9 @@ WHERE config_digest = $1 AND key = $2; func (d *db) WriteProtocolState(ctx context.Context, configDigest ocrtypes.ConfigDigest, key string, value []byte) (err error) { if value == nil { - _, err = d.q.ExecContext(ctx, `DELETE FROM ocr_protocol_states WHERE config_digest = $1 AND key = $2;`, configDigest, key) + _, err = d.ds.ExecContext(ctx, `DELETE FROM ocr_protocol_states WHERE config_digest = $1 AND key = $2;`, configDigest, key) } else { - _, err = d.q.ExecContext(ctx, ` + _, err = d.ds.ExecContext(ctx, ` INSERT INTO ocr_protocol_states (config_digest, key, value) VALUES ($1, $2, $3) ON CONFLICT (config_digest, key) DO UPDATE SET value = $3;`, configDigest, key, value) } diff --git a/core/services/ocr2/database_test.go b/core/services/ocr2/database_test.go index 6e4f8f5dd66..3e78249d087 100644 --- a/core/services/ocr2/database_test.go +++ b/core/services/ocr2/database_test.go @@ -16,7 +16,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" @@ -60,14 +59,13 @@ func Test_DB_ReadWriteState(t *testing.T) { sqlDB := setupDB(t) configDigest := testhelpers.MakeConfigDigest(t) - cfg := configtest.NewTestGeneralConfig(t) ethKeyStore := cltest.NewKeyStore(t, sqlDB).Eth() key, _ := cltest.MustInsertRandomKey(t, ethKeyStore) spec := MustInsertOCROracleSpec(t, sqlDB, key.EIP55Address) lggr := logger.TestLogger(t) t.Run("reads and writes state", func(t *testing.T) { - db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr, cfg.Database()) + db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr) state := ocrtypes.PersistentState{ Epoch: 1, HighestSentEpoch: 2, @@ -84,7 +82,7 @@ func Test_DB_ReadWriteState(t *testing.T) { }) t.Run("updates state", func(t *testing.T) { - db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr, cfg.Database()) + db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr) newState := ocrtypes.PersistentState{ Epoch: 2, HighestSentEpoch: 3, @@ -101,7 +99,7 @@ func Test_DB_ReadWriteState(t *testing.T) { }) t.Run("does not return result for wrong spec", func(t *testing.T) { - db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr, cfg.Database()) + db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr) state := ocrtypes.PersistentState{ Epoch: 3, HighestSentEpoch: 4, @@ -112,7 +110,7 @@ func Test_DB_ReadWriteState(t *testing.T) { require.NoError(t, err) // odb with different spec - db = ocr2.NewDB(sqlDB, -1, defaultPluginID, lggr, cfg.Database()) + db = ocr2.NewDB(sqlDB, -1, defaultPluginID, lggr) readState, err := db.ReadState(testutils.Context(t), configDigest) require.NoError(t, err) @@ -121,7 +119,7 @@ func Test_DB_ReadWriteState(t *testing.T) { }) t.Run("does not return result for wrong config digest", func(t *testing.T) { - db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr, cfg.Database()) + db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr) state := ocrtypes.PersistentState{ Epoch: 4, HighestSentEpoch: 5, @@ -151,14 +149,13 @@ func Test_DB_ReadWriteConfig(t *testing.T) { OffchainConfigVersion: 111, OffchainConfig: []byte{0x03, 0x04}, } - cfg := configtest.NewTestGeneralConfig(t) ethKeyStore := cltest.NewKeyStore(t, sqlDB).Eth() key, _ := cltest.MustInsertRandomKey(t, ethKeyStore) spec := MustInsertOCROracleSpec(t, sqlDB, key.EIP55Address) lggr := logger.TestLogger(t) t.Run("reads and writes config", func(t *testing.T) { - db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr, cfg.Database()) + db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr) err := db.WriteConfig(testutils.Context(t), config) require.NoError(t, err) @@ -170,7 +167,7 @@ func Test_DB_ReadWriteConfig(t *testing.T) { }) t.Run("updates config", func(t *testing.T) { - db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr, cfg.Database()) + db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr) newConfig := ocrtypes.ContractConfig{ ConfigDigest: testhelpers.MakeConfigDigest(t), @@ -188,12 +185,12 @@ func Test_DB_ReadWriteConfig(t *testing.T) { }) t.Run("does not return result for wrong spec", func(t *testing.T) { - db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr, cfg.Database()) + db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr) err := db.WriteConfig(testutils.Context(t), config) require.NoError(t, err) - db = ocr2.NewDB(sqlDB, -1, defaultPluginID, lggr, cfg.Database()) + db = ocr2.NewDB(sqlDB, -1, defaultPluginID, lggr) readConfig, err := db.ReadConfig(testutils.Context(t)) require.NoError(t, err) @@ -203,8 +200,8 @@ func Test_DB_ReadWriteConfig(t *testing.T) { t.Run("reads and writes config for multiple plugins", func(t *testing.T) { otherPluginID := int32(2) - db1 := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr, cfg.Database()) - db2 := ocr2.NewDB(sqlDB, spec.ID, otherPluginID, lggr, cfg.Database()) + db1 := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr) + db2 := ocr2.NewDB(sqlDB, spec.ID, otherPluginID, lggr) otherConfig := ocrtypes.ContractConfig{ ConfigDigest: testhelpers.MakeConfigDigest(t), @@ -238,15 +235,14 @@ func assertPendingTransmissionEqual(t *testing.T, pt1, pt2 ocrtypes.PendingTrans func Test_DB_PendingTransmissions(t *testing.T) { sqlDB := setupDB(t) - cfg := configtest.NewTestGeneralConfig(t) ethKeyStore := cltest.NewKeyStore(t, sqlDB).Eth() key, _ := cltest.MustInsertRandomKey(t, ethKeyStore) lggr := logger.TestLogger(t) spec := MustInsertOCROracleSpec(t, sqlDB, key.EIP55Address) spec2 := MustInsertOCROracleSpec(t, sqlDB, key.EIP55Address) - db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr, cfg.Database()) - db2 := ocr2.NewDB(sqlDB, spec2.ID, defaultPluginID, lggr, cfg.Database()) + db := ocr2.NewDB(sqlDB, spec.ID, defaultPluginID, lggr) + db2 := ocr2.NewDB(sqlDB, spec2.ID, defaultPluginID, lggr) configDigest := testhelpers.MakeConfigDigest(t) k := ocrtypes.ReportTimestamp{ @@ -436,7 +432,7 @@ func Test_DB_PendingTransmissions(t *testing.T) { require.Len(t, m, 1) // Didn't affect other oracleSpecIDs - db = ocr2.NewDB(sqlDB, spec2.ID, defaultPluginID, lggr, cfg.Database()) + db = ocr2.NewDB(sqlDB, spec2.ID, defaultPluginID, lggr) m, err = db.PendingTransmissionsWithConfigDigest(testutils.Context(t), configDigest) require.NoError(t, err) require.Len(t, m, 1) @@ -446,10 +442,8 @@ func Test_DB_PendingTransmissions(t *testing.T) { func Test_DB_ReadWriteProtocolState(t *testing.T) { sqlDB := setupDB(t) - cfg := configtest.NewTestGeneralConfig(t) - lggr := logger.TestLogger(t) - db := ocr2.NewDB(sqlDB, 0, defaultPluginID, lggr, cfg.Database()) + db := ocr2.NewDB(sqlDB, 0, defaultPluginID, lggr) cd1 := testhelpers.MakeConfigDigest(t) cd2 := testhelpers.MakeConfigDigest(t) ctx := testutils.Context(t) diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index 7a2ef532fd2..6c76b0ff9c9 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -9,7 +9,6 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/jmoiron/sqlx" "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "google.golang.org/grpc" @@ -70,7 +69,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/promwrapper" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/relay" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" @@ -111,7 +109,6 @@ type RelayGetter interface { Get(id types.RelayID) (loop.Relayer, error) } type Delegate struct { - db *sqlx.DB // legacy: prefer to use ds instead ds sqlutil.DataSource jobORM job.ORM bridgeORM bridges.ORM @@ -138,7 +135,6 @@ type DelegateConfig interface { plugins.RegistrarConfig OCR2() ocr2Config JobPipeline() jobPipelineConfig - Database() pg.QConfig Insecure() insecureConfig Mercury() coreconfig.Mercury Threshold() coreconfig.Threshold @@ -149,7 +145,6 @@ type delegateConfig struct { plugins.RegistrarConfig ocr2 ocr2Config jobPipeline jobPipelineConfig - database pg.QConfig insecure insecureConfig mercury mercuryConfig threshold thresholdConfig @@ -159,10 +154,6 @@ func (d *delegateConfig) JobPipeline() jobPipelineConfig { return d.jobPipeline } -func (d *delegateConfig) Database() pg.QConfig { - return d.database -} - func (d *delegateConfig) Insecure() insecureConfig { return d.insecure } @@ -212,12 +203,11 @@ type thresholdConfig interface { ThresholdKeyShare() string } -func NewDelegateConfig(ocr2Cfg ocr2Config, m coreconfig.Mercury, t coreconfig.Threshold, i insecureConfig, jp jobPipelineConfig, qconf pg.QConfig, pluginProcessCfg plugins.RegistrarConfig) DelegateConfig { +func NewDelegateConfig(ocr2Cfg ocr2Config, m coreconfig.Mercury, t coreconfig.Threshold, i insecureConfig, jp jobPipelineConfig, pluginProcessCfg plugins.RegistrarConfig) DelegateConfig { return &delegateConfig{ ocr2: ocr2Cfg, RegistrarConfig: pluginProcessCfg, jobPipeline: jp, - database: qconf, insecure: i, mercury: m, threshold: t, @@ -227,7 +217,6 @@ func NewDelegateConfig(ocr2Cfg ocr2Config, m coreconfig.Mercury, t coreconfig.Th var _ job.Delegate = (*Delegate)(nil) func NewDelegate( - db *sqlx.DB, ds sqlutil.DataSource, jobORM job.ORM, bridgeORM bridges.ORM, @@ -248,7 +237,6 @@ func NewDelegate( capabilitiesRegistry core.CapabilitiesRegistry, ) *Delegate { return &Delegate{ - db: db, ds: ds, jobORM: jobORM, bridgeORM: bridgeORM, @@ -382,7 +370,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi } lggr := logger.Sugared(d.lggr.Named(jb.ExternalJobID.String()).With(lggrCtx.Args()...)) - kvStore := job.NewKVStore(jb.ID, d.db, d.cfg.Database(), lggr) + kvStore := job.NewKVStore(jb.ID, d.ds, lggr) rid, err := spec.RelayID() if err != nil { @@ -404,7 +392,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi spec.RelayConfig["effectiveTransmitterID"] = effectiveTransmitterID spec.RelayConfig.ApplyDefaultsOCR2(d.cfg.OCR2()) - ocrDB := NewDB(d.db, spec.ID, 0, lggr, d.cfg.Database()) + ocrDB := NewDB(d.ds, spec.ID, 0, lggr) if d.peerWrapper == nil { return nil, errors.New("cannot setup OCR2 job service, libp2p peer was missing") } else if !d.peerWrapper.IsStarted() { @@ -412,7 +400,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi } ocrLogger := commonlogger.NewOCRWrapper(lggr, d.cfg.OCR2().TraceLogging(), func(msg string) { - lggr.ErrorIf(d.jobORM.RecordError(jb.ID, msg), "unable to record error") + lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") }) lc, err := validate.ToLocalConfig(d.cfg.OCR2(), d.cfg.Insecure(), *spec) @@ -475,8 +463,8 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi thresholdPluginId s4PluginId ) - thresholdPluginDB := NewDB(d.db, spec.ID, thresholdPluginId, lggr, d.cfg.Database()) - s4PluginDB := NewDB(d.db, spec.ID, s4PluginId, lggr, d.cfg.Database()) + thresholdPluginDB := NewDB(d.ds, spec.ID, thresholdPluginId, lggr) + s4PluginDB := NewDB(d.ds, spec.ID, s4PluginId, lggr) return d.newServicesOCR2Functions(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, thresholdPluginDB, s4PluginDB, lc, ocrLogger) case types.GenericPlugin: @@ -904,10 +892,10 @@ func (d *Delegate) newServicesLLO( kr := llo.NewOnchainKeyring(lggr, kbm) cfg := llo.DelegateConfig{ - Logger: lggr, - Queryer: pg.NewQ(d.db, lggr, d.cfg.Database()), - Runner: d.pipelineRunner, - Registry: d.streamRegistry, + Logger: lggr, + DataSource: d.ds, + Runner: d.pipelineRunner, + Registry: d.streamRegistry, JobName: jb.Name, @@ -1010,7 +998,7 @@ func (d *Delegate) newServicesDKG( if err2 != nil { return nil, fmt.Errorf("DKG services: failed to get chain %s: %w", rid.ChainID, err2) } - ocr2vrfRelayer := evmrelay.NewOCR2VRFRelayer(d.db, chain, lggr.Named("OCR2VRFRelayer"), d.ethKs) + ocr2vrfRelayer := evmrelay.NewOCR2VRFRelayer(chain, lggr.Named("OCR2VRFRelayer"), d.ethKs) dkgProvider, err2 := ocr2vrfRelayer.NewDKGProvider( types.RelayArgs{ ExternalJobID: jb.ExternalJobID, @@ -1041,20 +1029,7 @@ func (d *Delegate) newServicesDKG( OnchainKeyring: kb, MetricsRegisterer: prometheus.WrapRegistererWith(map[string]string{"job_name": jb.Name.ValueOrZero()}, prometheus.DefaultRegisterer), } - return dkg.NewDKGServices( - jb, - dkgProvider, - lggr, - ocrLogger, - d.dkgSignKs, - d.dkgEncryptKs, - chain.Client(), - oracleArgsNoPlugin, - d.db, - d.cfg.Database(), - chain.ID(), - spec.Relay, - ) + return dkg.NewDKGServices(jb, dkgProvider, lggr, ocrLogger, d.dkgSignKs, d.dkgEncryptKs, chain.Client(), oracleArgsNoPlugin, d.ds, chain.ID(), spec.Relay) } func (d *Delegate) newServicesOCR2VRF( @@ -1094,7 +1069,7 @@ func (d *Delegate) newServicesOCR2VRF( return nil, errors.Wrap(err2, "validate ocr2vrf plugin config") } - ocr2vrfRelayer := evmrelay.NewOCR2VRFRelayer(d.db, chain, lggr.Named("OCR2VRFRelayer"), d.ethKs) + ocr2vrfRelayer := evmrelay.NewOCR2VRFRelayer(chain, lggr.Named("OCR2VRFRelayer"), d.ethKs) transmitterID := spec.TransmitterID.String vrfProvider, err2 := ocr2vrfRelayer.NewOCR2VRFProvider( @@ -1179,11 +1154,11 @@ func (d *Delegate) newServicesOCR2VRF( ) vrfLogger := commonlogger.NewOCRWrapper(l.With( "vrfContractID", spec.ContractID), d.cfg.OCR2().TraceLogging(), func(msg string) { - lggr.ErrorIf(d.jobORM.RecordError(jb.ID, msg), "unable to record error") + lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") }) dkgLogger := commonlogger.NewOCRWrapper(l.With( "dkgContractID", cfg.DKGContractAddress), d.cfg.OCR2().TraceLogging(), func(msg string) { - lggr.ErrorIf(d.jobORM.RecordError(jb.ID, msg), "unable to record error") + lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") }) dkgReportingPluginFactoryDecorator := func(wrapped ocrtypes.ReportingPluginFactory) ocrtypes.ReportingPluginFactory { return promwrapper.NewPromFactory(wrapped, "DKG", string(types.NetworkEVM), chain.ID()) @@ -1222,7 +1197,7 @@ func (d *Delegate) newServicesOCR2VRF( KeyID: keyID, DKGReportingPluginFactoryDecorator: dkgReportingPluginFactoryDecorator, VRFReportingPluginFactoryDecorator: vrfReportingPluginFactoryDecorator, - DKGSharePersistence: persistence.NewShareDB(d.db, lggr.Named("DKGShareDB"), d.cfg.Database(), chain.ID(), spec.Relay), + DKGSharePersistence: persistence.NewShareDB(d.ds, lggr.Named("DKGShareDB"), chain.ID(), spec.Relay), }) if err2 != nil { return nil, errors.Wrap(err2, "new ocr2vrf") @@ -1449,7 +1424,7 @@ func (d *Delegate) newServicesOCR2Keepers20( return nil, fmt.Errorf("keepers2.0 services: failed to get chain (%s): %w", rid.ChainID, err2) } - keeperProvider, rgstry, encoder, logProvider, err2 := ocr2keeper.EVMDependencies20(ctx, jb, d.db, lggr, chain, d.ethKs, d.cfg.Database()) + keeperProvider, rgstry, encoder, logProvider, err2 := ocr2keeper.EVMDependencies20(ctx, jb, d.ds, lggr, chain, d.ethKs) if err2 != nil { return nil, errors.Wrap(err2, "could not build dependencies for ocr2 keepers") } @@ -1699,11 +1674,11 @@ func (d *Delegate) newServicesOCR2Functions( // errorLog implements [loop.ErrorLog] type errorLog struct { jobID int32 - recordError func(jobID int32, description string, qopts ...pg.QOpt) error + recordError func(ctx context.Context, jobID int32, description string) error } func (l *errorLog) SaveError(ctx context.Context, msg string) error { - return l.recordError(l.jobID, msg) + return l.recordError(ctx, l.jobID, msg) } type logWriter struct { diff --git a/core/services/ocr2/plugins/dkg/persistence/db.go b/core/services/ocr2/plugins/dkg/persistence/db.go index b8ecfbaceb4..07dad494ed7 100644 --- a/core/services/ocr2/plugins/dkg/persistence/db.go +++ b/core/services/ocr2/plugins/dkg/persistence/db.go @@ -16,11 +16,11 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types" "github.com/smartcontractkit/chainlink-vrf/types/hash" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) var ( @@ -52,16 +52,16 @@ var ( ) type shareDB struct { - q pg.Q + ds sqlutil.DataSource lggr logger.Logger chainID *big.Int chainType string } // NewShareDB creates a new DKG share database. -func NewShareDB(db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig, chainID *big.Int, chainType string) ocr2vrftypes.DKGSharePersistence { +func NewShareDB(ds sqlutil.DataSource, lggr logger.Logger, chainID *big.Int, chainType string) ocr2vrftypes.DKGSharePersistence { return &shareDB{ - q: pg.NewQ(db, lggr, cfg), + ds: ds, lggr: lggr, chainID: chainID, chainType: chainType, @@ -134,13 +134,13 @@ func (s *shareDB) WriteShareRecords( // Always upsert because we want the number of rows in the table to match // the number of members of the committee. - query := ` + _, err := s.ds.NamedExecContext(ctx, ` INSERT INTO dkg_shares (config_digest, key_id, dealer, marshaled_share_record, record_hash) VALUES (:config_digest, :key_id, :dealer, :marshaled_share_record, :record_hash) ON CONFLICT ON CONSTRAINT dkg_shares_pkey DO UPDATE SET marshaled_share_record = EXCLUDED.marshaled_share_record, record_hash = EXCLUDED.record_hash -` - return s.q.ExecQNamed(query, named[:]) +`, named[:]) + return err } // ReadShareRecords retrieves any share records in the database that correspond @@ -152,6 +152,7 @@ func (s *shareDB) ReadShareRecords( retrievedShares []ocr2vrftypes.PersistentShareSetRecord, err error, ) { + ctx := context.Background() //TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 lggr := s.lggr.With( "configDigest", hexutil.Encode(cfgDgst[:]), "keyID", hexutil.Encode(keyID[:])) @@ -177,9 +178,9 @@ WHERE config_digest = :config_digest if err != nil { return nil, errors.Wrap(err, "sqlx Named") } - query = s.q.Rebind(query) + query = s.ds.Rebind(query) var dkgShares []dkgShare - err = s.q.Select(&dkgShares, query, args...) + err = s.ds.SelectContext(ctx, &dkgShares, query, args...) if errors.Is(err, sql.ErrNoRows) { return nil, nil } diff --git a/core/services/ocr2/plugins/dkg/persistence/db_test.go b/core/services/ocr2/plugins/dkg/persistence/db_test.go index a3949ea70dc..dbc400a3468 100644 --- a/core/services/ocr2/plugins/dkg/persistence/db_test.go +++ b/core/services/ocr2/plugins/dkg/persistence/db_test.go @@ -22,7 +22,7 @@ import ( func setup(t testing.TB) (ocr2vrftypes.DKGSharePersistence, *sqlx.DB) { db := pgtest.NewSqlxDB(t) lggr := logger.TestLogger(t) - return NewShareDB(db, lggr, pgtest.NewQConfig(true), big.NewInt(1337), types.NetworkEVM), db + return NewShareDB(db, lggr, big.NewInt(1337), types.NetworkEVM), db } func TestShareDB_WriteShareRecords(t *testing.T) { diff --git a/core/services/ocr2/plugins/dkg/plugin.go b/core/services/ocr2/plugins/dkg/plugin.go index 65216ac1115..0364c5d9ab0 100644 --- a/core/services/ocr2/plugins/dkg/plugin.go +++ b/core/services/ocr2/plugins/dkg/plugin.go @@ -6,12 +6,12 @@ import ( "fmt" "math/big" - "github.com/jmoiron/sqlx" "github.com/pkg/errors" "github.com/smartcontractkit/libocr/commontypes" libocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-vrf/altbn_128" "github.com/smartcontractkit/chainlink-vrf/dkg" @@ -21,7 +21,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/dkg/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/dkg/persistence" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) @@ -34,8 +33,7 @@ func NewDKGServices( dkgEncryptKs keystore.DKGEncrypt, ethClient evmclient.Client, oracleArgsNoPlugin libocr2.OCR2OracleArgs, - db *sqlx.DB, - qConfig pg.QConfig, + ds sqlutil.DataSource, chainID *big.Int, network string, ) ([]job.ServiceCtx, error) { @@ -68,7 +66,7 @@ func NewDKGServices( if err != nil { return nil, errors.Wrap(err, "decode key ID") } - shareDB := persistence.NewShareDB(db, lggr.Named("DKGShareDB"), qConfig, chainID, network) + shareDB := persistence.NewShareDB(ds, lggr.Named("DKGShareDB"), chainID, network) oracleArgsNoPlugin.ReportingPluginFactory = dkg.NewReportingPluginFactory( encryptKey.KyberScalar(), signKey.KyberScalar(), diff --git a/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go b/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go index 0d6bc02e198..a33ab2a1bd2 100644 --- a/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go +++ b/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go @@ -47,7 +47,7 @@ func TestAdapter_Integration(t *testing.T) { keystore := keystore.NewInMemory(db, utils.FastScryptParams, logger) pipelineORM := pipeline.NewORM(db, logger, cfg.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) - jobORM := job.NewORM(db, pipelineORM, bridgesORM, keystore, logger, cfg.Database()) + jobORM := job.NewORM(db, pipelineORM, bridgesORM, keystore, logger) pr := pipeline.NewRunner( pipelineORM, bridgesORM, @@ -75,7 +75,7 @@ func TestAdapter_Integration(t *testing.T) { jb.Name = null.StringFrom("Job 1") jb.OCR2OracleSpec.TransmitterID = null.StringFrom(address.String()) jb.OCR2OracleSpec.PluginConfig["juelsPerFeeCoinSource"] = juelsPerFeeCoinSource - err = jobORM.CreateJob(&jb) + err = jobORM.CreateJob(ctx, &jb) require.NoError(t, err) pra := generic.NewPipelineRunnerAdapter(logger, jb, pr) results, err := pra.ExecuteRun(testutils.Context(t), spec, core.Vars{Vars: map[string]interface{}{"val": 1}}, core.Options{}) diff --git a/core/services/ocr2/plugins/ocr2keeper/util.go b/core/services/ocr2/plugins/ocr2keeper/util.go index 35bd62eeed8..339d8a89dfb 100644 --- a/core/services/ocr2/plugins/ocr2keeper/util.go +++ b/core/services/ocr2/plugins/ocr2keeper/util.go @@ -4,12 +4,11 @@ import ( "context" "fmt" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - "github.com/jmoiron/sqlx" - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ocr2keepers20 "github.com/smartcontractkit/chainlink-automation/pkg/v2" @@ -25,7 +24,6 @@ import ( evmregistry20 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20" evmregistry21 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21" evmregistry21transmit "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/transmit" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) type Encoder20 interface { @@ -44,9 +42,9 @@ var ( ErrNoChainFromSpec = fmt.Errorf("could not create chain from spec") ) -func EVMProvider(db *sqlx.DB, chain legacyevm.Chain, lggr logger.Logger, spec job.Job, ethKeystore keystore.Eth, dbCfg pg.QConfig) (evmrelay.OCR2KeeperProvider, error) { +func EVMProvider(ds sqlutil.DataSource, chain legacyevm.Chain, lggr logger.Logger, spec job.Job, ethKeystore keystore.Eth) (evmrelay.OCR2KeeperProvider, error) { oSpec := spec.OCR2OracleSpec - ocr2keeperRelayer := evmrelay.NewOCR2KeeperRelayer(db, chain, lggr.Named("OCR2KeeperRelayer"), ethKeystore, dbCfg) + ocr2keeperRelayer := evmrelay.NewOCR2KeeperRelayer(ds, chain, lggr.Named("OCR2KeeperRelayer"), ethKeystore) keeperProvider, err := ocr2keeperRelayer.NewOCR2KeeperProvider( types.RelayArgs{ @@ -70,11 +68,10 @@ func EVMProvider(db *sqlx.DB, chain legacyevm.Chain, lggr logger.Logger, spec jo func EVMDependencies20( ctx context.Context, spec job.Job, - db *sqlx.DB, + ds sqlutil.DataSource, lggr logger.Logger, chain legacyevm.Chain, ethKeystore keystore.Eth, - dbCfg pg.QConfig, ) (evmrelay.OCR2KeeperProvider, *evmregistry20.EvmRegistry, Encoder20, *evmregistry20.LogProvider, error) { var err error @@ -82,7 +79,7 @@ func EVMDependencies20( var registry *evmregistry20.EvmRegistry // the provider will be returned as a dependency - if keeperProvider, err = EVMProvider(db, chain, lggr, spec, ethKeystore, dbCfg); err != nil { + if keeperProvider, err = EVMProvider(ds, chain, lggr, spec, ethKeystore); err != nil { return nil, nil, nil, nil, err } diff --git a/core/services/ocrbootstrap/database.go b/core/services/ocrbootstrap/database.go index 86ade39a05d..ef63b75dd39 100644 --- a/core/services/ocrbootstrap/database.go +++ b/core/services/ocrbootstrap/database.go @@ -8,11 +8,12 @@ import ( "github.com/pkg/errors" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/logger" ) type db struct { - *sql.DB + ds sqlutil.DataSource oracleSpecID int32 lggr logger.Logger } @@ -20,12 +21,12 @@ type db struct { var _ ocrtypes.ConfigDatabase = &db{} // NewDB returns a new DB scoped to this oracleSpecID -func NewDB(sqldb *sql.DB, bootstrapSpecID int32, lggr logger.Logger) *db { - return &db{sqldb, bootstrapSpecID, lggr} +func NewDB(ds sqlutil.DataSource, bootstrapSpecID int32, lggr logger.Logger) *db { + return &db{ds, bootstrapSpecID, lggr} } func (d *db) ReadConfig(ctx context.Context) (c *ocrtypes.ContractConfig, err error) { - q := d.QueryRowContext(ctx, ` + q := d.ds.QueryRowxContext(ctx, ` SELECT config_digest, config_count, @@ -82,7 +83,7 @@ func (d *db) WriteConfig(ctx context.Context, c ocrtypes.ContractConfig) error { for _, s := range c.Signers { signers = append(signers, []byte(s)) } - _, err := d.ExecContext(ctx, ` + _, err := d.ds.ExecContext(ctx, ` INSERT INTO bootstrap_contract_configs ( bootstrap_spec_id, config_digest, diff --git a/core/services/ocrbootstrap/database_test.go b/core/services/ocrbootstrap/database_test.go index e00e318c69c..eaad863c88b 100644 --- a/core/services/ocrbootstrap/database_test.go +++ b/core/services/ocrbootstrap/database_test.go @@ -52,7 +52,7 @@ func Test_DB_ReadWriteConfig(t *testing.T) { lggr := logger.TestLogger(t) t.Run("reads and writes config", func(t *testing.T) { - db := ocrbootstrap.NewDB(sqlDB.DB, spec.ID, lggr) + db := ocrbootstrap.NewDB(sqlDB, spec.ID, lggr) err := db.WriteConfig(testutils.Context(t), config) require.NoError(t, err) @@ -64,7 +64,7 @@ func Test_DB_ReadWriteConfig(t *testing.T) { }) t.Run("updates config", func(t *testing.T) { - db := ocrbootstrap.NewDB(sqlDB.DB, spec.ID, lggr) + db := ocrbootstrap.NewDB(sqlDB, spec.ID, lggr) newConfig := ocrtypes.ContractConfig{ ConfigDigest: testhelpers.MakeConfigDigest(t), @@ -82,12 +82,12 @@ func Test_DB_ReadWriteConfig(t *testing.T) { }) t.Run("does not return result for wrong spec", func(t *testing.T) { - db := ocrbootstrap.NewDB(sqlDB.DB, spec.ID, lggr) + db := ocrbootstrap.NewDB(sqlDB, spec.ID, lggr) err := db.WriteConfig(testutils.Context(t), config) require.NoError(t, err) - db = ocrbootstrap.NewDB(sqlDB.DB, -1, lggr) + db = ocrbootstrap.NewDB(sqlDB, -1, lggr) readConfig, err := db.ReadConfig(testutils.Context(t)) require.NoError(t, err) diff --git a/core/services/ocrbootstrap/delegate.go b/core/services/ocrbootstrap/delegate.go index 84f473088bb..0bb7a0ca2ba 100644 --- a/core/services/ocrbootstrap/delegate.go +++ b/core/services/ocrbootstrap/delegate.go @@ -7,12 +7,11 @@ import ( "github.com/pkg/errors" - "github.com/jmoiron/sqlx" - ocr "github.com/smartcontractkit/libocr/offchainreporting2plus" commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -27,7 +26,7 @@ type RelayGetter interface { // Delegate creates Bootstrap jobs type Delegate struct { - db *sqlx.DB + ds sqlutil.DataSource jobORM job.ORM peerWrapper *ocrcommon.SingletonPeerWrapper ocr2Cfg validate.OCR2Config @@ -48,7 +47,7 @@ type relayConfig struct { // NewDelegateBootstrap creates a new Delegate func NewDelegateBootstrap( - db *sqlx.DB, + ds sqlutil.DataSource, jobORM job.ORM, peerWrapper *ocrcommon.SingletonPeerWrapper, lggr logger.Logger, @@ -57,7 +56,7 @@ func NewDelegateBootstrap( relayers RelayGetter, ) *Delegate { return &Delegate{ - db: db, + ds: ds, jobORM: jobORM, peerWrapper: peerWrapper, lggr: logger.Sugared(lggr), @@ -166,10 +165,10 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) (services [] bootstrapNodeArgs := ocr.BootstrapperArgs{ BootstrapperFactory: d.peerWrapper.Peer2, ContractConfigTracker: configProvider.ContractConfigTracker(), - Database: NewDB(d.db.DB, spec.ID, lggr), + Database: NewDB(d.ds, spec.ID, lggr), LocalConfig: lc, Logger: commonlogger.NewOCRWrapper(lggr.Named("OCRBootstrap"), d.ocr2Cfg.TraceLogging(), func(msg string) { - logger.Sugared(lggr).ErrorIf(d.jobORM.RecordError(jb.ID, msg), "unable to record error") + logger.Sugared(lggr).ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") }), OffchainConfigDigester: configProvider.OffchainConfigDigester(), } diff --git a/core/services/ocrcommon/discoverer_database.go b/core/services/ocrcommon/discoverer_database.go index 9413b11ad07..ea75f9e6d21 100644 --- a/core/services/ocrcommon/discoverer_database.go +++ b/core/services/ocrcommon/discoverer_database.go @@ -2,25 +2,26 @@ package ocrcommon import ( "context" - "database/sql" "github.com/lib/pq" "github.com/pkg/errors" "go.uber.org/multierr" ocrnetworking "github.com/smartcontractkit/libocr/networking/types" + + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" ) var _ ocrnetworking.DiscovererDatabase = &DiscovererDatabase{} type DiscovererDatabase struct { - db *sql.DB + ds sqlutil.DataSource peerID string } -func NewDiscovererDatabase(db *sql.DB, peerID string) *DiscovererDatabase { +func NewDiscovererDatabase(ds sqlutil.DataSource, peerID string) *DiscovererDatabase { return &DiscovererDatabase{ - db, + ds, peerID, } } @@ -28,7 +29,7 @@ func NewDiscovererDatabase(db *sql.DB, peerID string) *DiscovererDatabase { // StoreAnnouncement has key-value-store semantics and stores a peerID (key) and an associated serialized // announcement (value). func (d *DiscovererDatabase) StoreAnnouncement(ctx context.Context, peerID string, ann []byte) error { - _, err := d.db.ExecContext(ctx, ` + _, err := d.ds.ExecContext(ctx, ` INSERT INTO ocr_discoverer_announcements (local_peer_id, remote_peer_id, ann, created_at, updated_at) VALUES ($1,$2,$3,NOW(),NOW()) ON CONFLICT (local_peer_id, remote_peer_id) DO UPDATE SET ann = EXCLUDED.ann, @@ -40,7 +41,7 @@ updated_at = EXCLUDED.updated_at // ReadAnnouncements returns one serialized announcement (if available) for each of the peerIDs in the form of a map // keyed by each announcement's corresponding peer ID. func (d *DiscovererDatabase) ReadAnnouncements(ctx context.Context, peerIDs []string) (results map[string][]byte, err error) { - rows, err := d.db.QueryContext(ctx, ` + rows, err := d.ds.QueryContext(ctx, ` SELECT remote_peer_id, ann FROM ocr_discoverer_announcements WHERE remote_peer_id = ANY($1) AND local_peer_id = $2`, pq.Array(peerIDs), d.peerID) if err != nil { return nil, errors.Wrap(err, "DiscovererDatabase failed to ReadAnnouncements") diff --git a/core/services/ocrcommon/discoverer_database_test.go b/core/services/ocrcommon/discoverer_database_test.go index b7a79e92bce..23d5ad661a4 100644 --- a/core/services/ocrcommon/discoverer_database_test.go +++ b/core/services/ocrcommon/discoverer_database_test.go @@ -16,7 +16,7 @@ import ( ) func Test_DiscovererDatabase(t *testing.T) { - db := pgtest.NewSqlDB(t) + db := pgtest.NewSqlxDB(t) localPeerID1 := mustRandomP2PPeerID(t) localPeerID2 := mustRandomP2PPeerID(t) diff --git a/core/services/ocrcommon/peer_wrapper.go b/core/services/ocrcommon/peer_wrapper.go index 02bdd9cee7d..97c429f9a5f 100644 --- a/core/services/ocrcommon/peer_wrapper.go +++ b/core/services/ocrcommon/peer_wrapper.go @@ -4,7 +4,6 @@ import ( "context" "io" - "github.com/jmoiron/sqlx" "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" @@ -14,12 +13,12 @@ import ( commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) type PeerWrapperOCRConfig interface { @@ -43,8 +42,7 @@ type ( keyStore keystore.Master p2pCfg config.P2P ocrCfg PeerWrapperOCRConfig - dbConfig pg.QConfig - db *sqlx.DB + ds sqlutil.DataSource lggr logger.Logger PeerID p2pkey.PeerID @@ -69,13 +67,12 @@ func ValidatePeerWrapperConfig(config config.P2P) error { // NewSingletonPeerWrapper creates a new peer based on the p2p keys in the keystore // It currently only supports one peerID/key // It should be fairly easy to modify it to support multiple peerIDs/keys using e.g. a map -func NewSingletonPeerWrapper(keyStore keystore.Master, p2pCfg config.P2P, ocrCfg PeerWrapperOCRConfig, dbConfig pg.QConfig, db *sqlx.DB, lggr logger.Logger) *SingletonPeerWrapper { +func NewSingletonPeerWrapper(keyStore keystore.Master, p2pCfg config.P2P, ocrCfg PeerWrapperOCRConfig, ds sqlutil.DataSource, lggr logger.Logger) *SingletonPeerWrapper { return &SingletonPeerWrapper{ keyStore: keyStore, p2pCfg: p2pCfg, ocrCfg: ocrCfg, - dbConfig: dbConfig, - db: db, + ds: ds, lggr: lggr.Named("SingletonPeerWrapper"), } } @@ -120,7 +117,7 @@ func (p *SingletonPeerWrapper) peerConfig() (ocrnetworking.PeerConfig, error) { } p.PeerID = key.PeerID() - discovererDB := NewDiscovererDatabase(p.db.DB, p.PeerID.Raw()) + discovererDB := NewDiscovererDatabase(p.ds, p.PeerID.Raw()) config := p.p2pCfg peerConfig := ocrnetworking.PeerConfig{ diff --git a/core/services/ocrcommon/peer_wrapper_test.go b/core/services/ocrcommon/peer_wrapper_test.go index e87f211fd21..a47ed19ec56 100644 --- a/core/services/ocrcommon/peer_wrapper_test.go +++ b/core/services/ocrcommon/peer_wrapper_test.go @@ -34,7 +34,7 @@ func Test_SingletonPeerWrapper_Start(t *testing.T) { c.P2P.V2.Enabled = ptr(true) }) keyStore := cltest.NewKeyStore(t, db) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), cfg.Database(), db, logger.TestLogger(t)) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), db, logger.TestLogger(t)) require.Contains(t, pw.Start(testutils.Context(t)).Error(), "No P2P keys found in keystore. Peer wrapper will not be fully initialized") }) @@ -49,7 +49,7 @@ func Test_SingletonPeerWrapper_Start(t *testing.T) { c.P2P.V2.ListenAddresses = &[]string{fmt.Sprintf("127.0.0.1:%d", freeport.GetOne(t))} c.P2P.PeerID = ptr(k.PeerID()) }) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), cfg.Database(), db, logger.TestLogger(t)) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), db, logger.TestLogger(t)) servicetest.Run(t, pw) require.Equal(t, k.PeerID(), pw.PeerID) @@ -66,7 +66,7 @@ func Test_SingletonPeerWrapper_Start(t *testing.T) { _, err := keyStore.P2P().Create(ctx) require.NoError(t, err) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), cfg.Database(), db, logger.TestLogger(t)) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), db, logger.TestLogger(t)) require.Contains(t, pw.Start(testutils.Context(t)).Error(), "unable to find P2P key with id") }) @@ -83,7 +83,7 @@ func Test_SingletonPeerWrapper_Start(t *testing.T) { c.P2P.PeerID = ptr(k2.PeerID()) }) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), cfg.Database(), db, logger.TestLogger(t)) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), db, logger.TestLogger(t)) servicetest.Run(t, pw) require.Equal(t, k2.PeerID(), pw.PeerID) @@ -101,7 +101,7 @@ func Test_SingletonPeerWrapper_Start(t *testing.T) { _, err := keyStore.P2P().Create(ctx) require.NoError(t, err) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), cfg.Database(), db, logger.TestLogger(t)) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), db, logger.TestLogger(t)) require.Contains(t, pw.Start(testutils.Context(t)).Error(), "unable to find P2P key with id") }) @@ -131,7 +131,7 @@ func Test_SingletonPeerWrapper_Close(t *testing.T) { }) - pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), cfg.Database(), db, logger.TestLogger(t)) + pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), db, logger.TestLogger(t)) require.NoError(t, pw.Start(testutils.Context(t))) require.True(t, pw.IsStarted(), "Should have started successfully") @@ -139,7 +139,7 @@ func Test_SingletonPeerWrapper_Close(t *testing.T) { /* If peer is still stuck in listenLoop, we will get a bind error trying to start on the same port */ require.False(t, pw.IsStarted()) - pw = ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), cfg.Database(), db, logger.TestLogger(t)) + pw = ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), db, logger.TestLogger(t)) require.NoError(t, pw.Start(testutils.Context(t)), "Should have shut down gracefully, and be able to re-use same port") require.True(t, pw.IsStarted(), "Should have started successfully") require.NoError(t, pw.Close()) diff --git a/core/services/pg/connection.go b/core/services/pg/connection.go index 79d74c6e610..e8b6f3af429 100644 --- a/core/services/pg/connection.go +++ b/core/services/pg/connection.go @@ -1,6 +1,7 @@ package pg import ( + "database/sql" "fmt" "log" "os" @@ -18,6 +19,10 @@ import ( "github.com/XSAM/otelsql" ) +// NOTE: This is the default level in Postgres anyway, we just make it +// explicit here +const defaultIsolation = sql.LevelReadCommitted + var MinRequiredPGVersion = 110000 func init() { diff --git a/core/services/pg/lease_lock.go b/core/services/pg/lease_lock.go index 58ec2781245..885115d26c7 100644 --- a/core/services/pg/lease_lock.go +++ b/core/services/pg/lease_lock.go @@ -12,6 +12,7 @@ import ( "github.com/pkg/errors" "go.uber.org/multierr" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -248,10 +249,12 @@ func (l *leaseLock) getLease(ctx context.Context, isInitial bool) (gotLease bool // NOTE: Uses database time for all calculations since it's conceivable // that node local times might be skewed compared to each other - err = sqlxTransactionQ(ctx, l.conn, l.logger, func(tx Queryer) error { + err = sqlutil.TransactConn(ctx, func(ds sqlutil.DataSource) sqlutil.DataSource { + return ds + }, l.conn, nil, func(tx sqlutil.DataSource) error { if isInitial { for _, query := range initialSQL { - if _, err = tx.Exec(query); err != nil { + if _, err = tx.ExecContext(ctx, query); err != nil { return errors.Wrap(err, "failed to create initial lease_lock table") } } @@ -259,7 +262,7 @@ func (l *leaseLock) getLease(ctx context.Context, isInitial bool) (gotLease bool // Upsert the lease_lock, only overwriting an existing one if the existing one has expired var res sql.Result - res, err = tx.Exec(` + res, err = tx.ExecContext(ctx, ` INSERT INTO lease_lock (client_id, expires_at) VALUES ($1, NOW()+$2::interval) ON CONFLICT ((client_id IS NOT NULL)) DO UPDATE SET client_id = EXCLUDED.client_id, expires_at = EXCLUDED.expires_at diff --git a/core/services/pg/q.go b/core/services/pg/q.go deleted file mode 100644 index 433023ddbc9..00000000000 --- a/core/services/pg/q.go +++ /dev/null @@ -1,384 +0,0 @@ -package pg - -import ( - "context" - "database/sql" - "fmt" - "strconv" - "strings" - "sync" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/jmoiron/sqlx" - "github.com/lib/pq" - "github.com/pkg/errors" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" -) - -// QOpt is deprecated. Use [sqlutil.DataSource] with [sqlutil.QueryHook]s instead. -// -// QOpt pattern for ORM methods aims to clarify usage and remove some common footguns, notably: -// -// 1. It should be easy and obvious how to pass a parent context or a transaction into an ORM method -// 2. Simple queries should not be cluttered -// 3. It should have compile-time safety and be explicit -// 4. It should enforce some sort of context deadline on all queries by default -// 5. It should optimise for clarity and readability -// 6. It should mandate using sqlx everywhere, gorm is forbidden in new code -// 7. It should make using sqlx a little more convenient by wrapping certain methods -// 8. It allows easier mocking of DB calls (Queryer is an interface) -// -// The two main concepts introduced are: -// -// A `Q` struct that wraps a `sqlx.DB` or `sqlx.Tx` and implements the `pg.Queryer` interface. -// -// This struct is initialised with `QOpts` which define how the queryer should behave. `QOpts` can define a parent context, an open transaction or other options to configure the Queryer. -// -// A sample ORM method looks like this: -// -// func (o *orm) GetFoo(id int64, qopts ...pg.QOpt) (Foo, error) { -// q := pg.NewQ(q, qopts...) -// return q.Exec(...) -// } -// -// Now you can call it like so: -// -// orm.GetFoo(1) // will automatically have default query timeout context set -// orm.GetFoo(1, pg.WithParentCtx(ctx)) // will wrap the supplied parent context with the default query context -// orm.GetFoo(1, pg.WithQueryer(tx)) // allows to pass in a running transaction or anything else that implements Queryer -// orm.GetFoo(q, pg.WithQueryer(tx), pg.WithParentCtx(ctx)) // options can be combined -type QOpt func(*Q) - -// WithQueryer sets the queryer -func WithQueryer(queryer Queryer) QOpt { - return func(q *Q) { - if q.Queryer != nil { - panic("queryer already set") - } - q.Queryer = queryer - } -} - -// WithParentCtx sets or overwrites the parent ctx -func WithParentCtx(ctx context.Context) QOpt { - return func(q *Q) { - q.ParentCtx = ctx - } -} - -// If the parent has a timeout, just use that instead of DefaultTimeout -func WithParentCtxInheritTimeout(ctx context.Context) QOpt { - return func(q *Q) { - q.ParentCtx = ctx - deadline, ok := q.ParentCtx.Deadline() - if ok { - q.QueryTimeout = time.Until(deadline) - } - } -} - -// WithLongQueryTimeout prevents the usage of the `DefaultQueryTimeout` duration and uses `OneMinuteQueryTimeout` instead -// Some queries need to take longer when operating over big chunks of data, like deleting jobs, but we need to keep some upper bound timeout -func WithLongQueryTimeout() QOpt { - return func(q *Q) { - q.QueryTimeout = longQueryTimeout - } -} - -var _ Queryer = Q{} - -type QConfig interface { - LogSQL() bool - DefaultQueryTimeout() time.Duration -} - -// Q wraps an underlying queryer (either a *sqlx.DB or a *sqlx.Tx) -// -// It is designed to make handling *sqlx.Tx or *sqlx.DB a little bit safer by -// preventing footguns such as having no deadline on contexts. -// -// It also handles nesting transactions. -// -// It automatically adds the default context deadline to all non-context -// queries (if you _really_ want to issue a query without a context, use the -// underlying Queryer) -// -// This is not the prettiest construct but without macros its about the best we -// can do. -// Deprecated: Use a `sqlutil.DataSource` with `sqlutil.QueryHook`s instead -type Q struct { - Queryer - ParentCtx context.Context - db *sqlx.DB - logger logger.SugaredLogger - config QConfig - QueryTimeout time.Duration -} - -func NewQ(db *sqlx.DB, lggr logger.Logger, config QConfig, qopts ...QOpt) (q Q) { - for _, opt := range qopts { - opt(&q) - } - - q.db = db - // skip two levels since we use internal helpers and also want to point up the stack to the caller of the Q method. - q.logger = logger.Sugared(logger.Helper(lggr, 2)) - q.config = config - - if q.Queryer == nil { - q.Queryer = db - } - if q.ParentCtx == nil { - q.ParentCtx = context.Background() - } - if q.QueryTimeout <= 0 { - q.QueryTimeout = q.config.DefaultQueryTimeout() - } - return -} - -func (q Q) originalLogger() logger.Logger { - return logger.Helper(q.logger, -2) -} - -func PrepareQueryRowx(q Queryer, sql string, dest interface{}, arg interface{}) error { - stmt, err := q.PrepareNamed(sql) - if err != nil { - return errors.Wrap(err, "error preparing named statement") - } - defer stmt.Close() - return errors.Wrap(stmt.QueryRowx(arg).Scan(dest), "error querying row") -} - -func (q Q) WithOpts(qopts ...QOpt) Q { - return NewQ(q.db, q.originalLogger(), q.config, qopts...) -} - -func (q Q) Context() (context.Context, context.CancelFunc) { - return context.WithTimeout(q.ParentCtx, q.QueryTimeout) -} - -func (q Q) Transaction(fc func(q Queryer) error, txOpts ...TxOption) error { - ctx, cancel := q.Context() - defer cancel() - return SqlxTransaction(ctx, q.Queryer, q.originalLogger(), fc, txOpts...) -} - -// CAUTION: A subtle problem lurks here, because the following code is buggy: -// -// ctx, cancel := context.WithCancel(context.Background()) -// rows, err := db.QueryContext(ctx, "SELECT foo") -// cancel() // canceling here "poisons" the scan below -// for rows.Next() { -// rows.Scan(...) -// } -// -// We must cancel the context only after we have completely finished using the -// returned rows or result from the query/exec -// -// For this reasons, the following functions return a context.CancelFunc and it -// is up to the caller to ensure that cancel is called after it has finished -// -// Generally speaking, it makes more sense to use Get/Select in most cases, -// which avoids this problem -func (q Q) ExecQIter(query string, args ...interface{}) (sql.Result, context.CancelFunc, error) { - ctx, cancel := q.Context() - - ql := q.newQueryLogger(query, args) - ql.logSqlQuery() - defer ql.postSqlLog(ctx, time.Now()) - - res, err := q.Queryer.ExecContext(ctx, query, args...) - return res, cancel, ql.withLogError(err) -} -func (q Q) ExecQWithRowsAffected(query string, args ...interface{}) (int64, error) { - res, cancel, err := q.ExecQIter(query, args...) - defer cancel() - if err != nil { - return 0, err - } - - rowsDeleted, err := res.RowsAffected() - return rowsDeleted, err -} -func (q Q) ExecQ(query string, args ...interface{}) error { - ctx, cancel := q.Context() - defer cancel() - - ql := q.newQueryLogger(query, args) - ql.logSqlQuery() - defer ql.postSqlLog(ctx, time.Now()) - - _, err := q.Queryer.ExecContext(ctx, query, args...) - return ql.withLogError(err) -} -func (q Q) ExecQNamed(query string, arg interface{}) (err error) { - query, args, err := q.BindNamed(query, arg) - if err != nil { - return errors.Wrap(err, "error binding arg") - } - ctx, cancel := q.Context() - defer cancel() - - ql := q.newQueryLogger(query, args) - ql.logSqlQuery() - defer ql.postSqlLog(ctx, time.Now()) - - _, err = q.Queryer.ExecContext(ctx, query, args...) - return ql.withLogError(err) -} - -// Select and Get are safe to wrap the context cancellation because the rows -// are entirely consumed within the call -func (q Q) Select(dest interface{}, query string, args ...interface{}) error { - ctx, cancel := q.Context() - defer cancel() - - ql := q.newQueryLogger(query, args) - ql.logSqlQuery() - defer ql.postSqlLog(ctx, time.Now()) - - return ql.withLogError(q.Queryer.SelectContext(ctx, dest, query, args...)) -} - -func (q Q) SelectNamed(dest interface{}, query string, arg interface{}) error { - query, args, err := q.BindNamed(query, arg) - if err != nil { - return errors.Wrap(err, "error binding arg") - } - return q.Select(dest, query, args...) -} - -func (q Q) Get(dest interface{}, query string, args ...interface{}) error { - ctx, cancel := q.Context() - defer cancel() - - ql := q.newQueryLogger(query, args) - ql.logSqlQuery() - defer ql.postSqlLog(ctx, time.Now()) - - return ql.withLogError(q.Queryer.GetContext(ctx, dest, query, args...)) -} - -func (q Q) GetNamed(sql string, dest interface{}, arg interface{}) error { - query, args, err := q.BindNamed(sql, arg) - if err != nil { - return errors.Wrap(err, "error binding arg") - } - ctx, cancel := q.Context() - defer cancel() - - ql := q.newQueryLogger(query, args) - ql.logSqlQuery() - defer ql.postSqlLog(ctx, time.Now()) - - return ql.withLogError(errors.Wrap(q.GetContext(ctx, dest, query, args...), "error in get query")) -} - -func (q Q) newQueryLogger(query string, args []interface{}) *queryLogger { - return &queryLogger{Q: q, query: query, args: args, str: sync.OnceValue(func() string { - return sprintQ(query, args) - })} -} - -// sprintQ formats the query with the given args and returns the resulting string. -func sprintQ(query string, args []interface{}) string { - if args == nil { - return query - } - var pairs []string - for i, arg := range args { - // We print by type so one can directly take the logged query string and execute it manually in pg. - // Annoyingly it seems as though the logger itself will add an extra \, so you still have to remove that. - switch v := arg.(type) { - case []byte: - pairs = append(pairs, fmt.Sprintf("$%d", i+1), fmt.Sprintf("'\\x%x'", v)) - case common.Address: - pairs = append(pairs, fmt.Sprintf("$%d", i+1), fmt.Sprintf("'\\x%x'", v.Bytes())) - case common.Hash: - pairs = append(pairs, fmt.Sprintf("$%d", i+1), fmt.Sprintf("'\\x%x'", v.Bytes())) - case pq.ByteaArray: - pairs = append(pairs, fmt.Sprintf("$%d", i+1)) - if v == nil { - pairs = append(pairs, "NULL") - continue - } - if len(v) == 0 { - pairs = append(pairs, "ARRAY[]") - continue - } - var s strings.Builder - fmt.Fprintf(&s, "ARRAY['\\x%x'", v[0]) - for j := 1; j < len(v); j++ { - fmt.Fprintf(&s, ",'\\x%x'", v[j]) - } - pairs = append(pairs, fmt.Sprintf("%s]", s.String())) - case string: - pairs = append(pairs, fmt.Sprintf("$%d", i+1), fmt.Sprintf("'%s'", v)) - default: - pairs = append(pairs, fmt.Sprintf("$%d", i+1), fmt.Sprintf("%v", v)) - } - } - replacer := strings.NewReplacer(pairs...) - queryWithVals := replacer.Replace(query) - return strings.ReplaceAll(strings.ReplaceAll(queryWithVals, "\n", " "), "\t", " ") -} - -// queryLogger extends Q with logging helpers for a particular query w/ args. -type queryLogger struct { - Q - - query string - args []interface{} - - str func() string -} - -func (q *queryLogger) String() string { - return q.str() -} - -func (q *queryLogger) logSqlQuery() { - if q.config != nil && q.config.LogSQL() { - q.logger.Debugw("SQL QUERY", "sql", q) - } -} - -func (q *queryLogger) withLogError(err error) error { - if err != nil && !errors.Is(err, sql.ErrNoRows) && q.config != nil && q.config.LogSQL() { - q.logger.Errorw("SQL ERROR", "err", err, "sql", q) - } - return err -} - -// postSqlLog logs about context cancellation and timing after a query returns. -// Queries which use their full timeout log critical level. More than 50% log error, and 10% warn. -func (q *queryLogger) postSqlLog(ctx context.Context, begin time.Time) { - elapsed := time.Since(begin) - if ctx.Err() != nil { - q.logger.Debugw("SQL CONTEXT CANCELLED", "ms", elapsed.Milliseconds(), "err", ctx.Err(), "sql", q) - } - - timeout := q.QueryTimeout - if timeout <= 0 { - timeout = DefaultQueryTimeout - } - - pct := float64(elapsed) / float64(timeout) - pct *= 100 - - kvs := []any{"ms", elapsed.Milliseconds(), "timeout", timeout.Milliseconds(), "percent", strconv.FormatFloat(pct, 'f', 1, 64), "sql", q} - - if elapsed >= timeout { - q.logger.Criticalw("SLOW SQL QUERY", kvs...) - } else if errThreshold := timeout / 5; errThreshold > 0 && elapsed > errThreshold { - q.logger.Errorw("SLOW SQL QUERY", kvs...) - } else if warnThreshold := timeout / 10; warnThreshold > 0 && elapsed > warnThreshold { - q.logger.Warnw("SLOW SQL QUERY", kvs...) - } - - sqlutil.PromSQLQueryTime.Observe(pct) -} diff --git a/core/services/pg/q_test.go b/core/services/pg/q_test.go deleted file mode 100644 index 81a883789df..00000000000 --- a/core/services/pg/q_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package pg - -import ( - "testing" - - "github.com/google/uuid" - "github.com/jmoiron/sqlx" - "github.com/lib/pq" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/store/dialects" -) - -func Test_sprintQ(t *testing.T) { - for _, tt := range []struct { - name string - query string - args []interface{} - exp string - }{ - {"none", - "SELECT * FROM table;", - nil, - "SELECT * FROM table;"}, - {"one", - "SELECT $1 FROM table;", - []interface{}{"foo"}, - "SELECT 'foo' FROM table;"}, - {"two", - "SELECT $1 FROM table WHERE bar = $2;", - []interface{}{"foo", 1}, - "SELECT 'foo' FROM table WHERE bar = 1;"}, - {"limit", - "SELECT $1 FROM table LIMIT $2;", - []interface{}{"foo", Limit(10)}, - "SELECT 'foo' FROM table LIMIT 10;"}, - {"limit-all", - "SELECT $1 FROM table LIMIT $2;", - []interface{}{"foo", Limit(-1)}, - "SELECT 'foo' FROM table LIMIT NULL;"}, - {"bytea", - "SELECT $1 FROM table WHERE b = $2;", - []interface{}{"foo", []byte{0x0a}}, - "SELECT 'foo' FROM table WHERE b = '\\x0a';"}, - {"bytea[]", - "SELECT $1 FROM table WHERE b = $2;", - []interface{}{"foo", pq.ByteaArray([][]byte{{0xa}, {0xb}})}, - "SELECT 'foo' FROM table WHERE b = ARRAY['\\x0a','\\x0b'];"}, - } { - t.Run(tt.name, func(t *testing.T) { - got := sprintQ(tt.query, tt.args) - t.Log(tt.query, tt.args) - t.Log(got) - require.Equal(t, tt.exp, got) - }) - } -} - -func Test_ExecQWithRowsAffected(t *testing.T) { - testutils.SkipShortDB(t) - db, err := sqlx.Open(string(dialects.TransactionWrappedPostgres), uuid.New().String()) - require.NoError(t, err) - q := NewQ(db, logger.NullLogger, NewQConfig(false)) - - require.NoError(t, q.ExecQ("CREATE TABLE testtable (a TEXT, b TEXT)")) - - rows, err := q.ExecQWithRowsAffected("INSERT INTO testtable (a, b) VALUES ($1, $2)", "foo", "bar") - require.NoError(t, err) - assert.Equal(t, int64(1), rows) - - rows, err = q.ExecQWithRowsAffected("INSERT INTO testtable (a, b) VALUES ($1, $1), ($2, $2), ($1, $2)", "foo", "bar") - require.NoError(t, err) - assert.Equal(t, int64(3), rows) - - rows, err = q.ExecQWithRowsAffected("delete from testtable") - require.NoError(t, err) - assert.Equal(t, int64(4), rows) - - rows, err = q.ExecQWithRowsAffected("delete from testtable") - require.NoError(t, err) - assert.Equal(t, int64(0), rows) -} diff --git a/core/services/pg/sqlx.go b/core/services/pg/sqlx.go index 76eae792cbf..9c99142e5c9 100644 --- a/core/services/pg/sqlx.go +++ b/core/services/pg/sqlx.go @@ -4,12 +4,8 @@ import ( "context" "database/sql" - "github.com/pkg/errors" - mapper "github.com/scylladb/go-reflectx" - "github.com/jmoiron/sqlx" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/scylladb/go-reflectx" ) // Queryer is deprecated. Use sqlutil.DataSource instead @@ -32,22 +28,6 @@ type Queryer interface { func WrapDbWithSqlx(rdb *sql.DB) *sqlx.DB { db := sqlx.NewDb(rdb, "postgres") - db.MapperFunc(mapper.CamelToSnakeASCII) + db.MapperFunc(reflectx.CamelToSnakeASCII) return db } - -func SqlxTransaction(ctx context.Context, q Queryer, lggr logger.Logger, fc func(q Queryer) error, txOpts ...TxOption) (err error) { - switch db := q.(type) { - case *sqlx.Tx: - // nested transaction: just use the outer transaction - err = fc(db) - case *sqlx.DB: - err = sqlxTransactionQ(ctx, db, lggr, fc, txOpts...) - case Q: - err = sqlxTransactionQ(ctx, db.db, lggr, fc, txOpts...) - default: - err = errors.Errorf("invalid db type: %T", q) - } - - return -} diff --git a/core/services/pg/transaction.go b/core/services/pg/transaction.go deleted file mode 100644 index d60270b4fe8..00000000000 --- a/core/services/pg/transaction.go +++ /dev/null @@ -1,95 +0,0 @@ -package pg - -import ( - "context" - "database/sql" - "fmt" - "time" - - "github.com/getsentry/sentry-go" - "github.com/jmoiron/sqlx" - "github.com/pkg/errors" - "go.uber.org/multierr" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - corelogger "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -// NOTE: This is the default level in Postgres anyway, we just make it -// explicit here -const defaultIsolation = sql.LevelReadCommitted - -// TxOption is a functional option for SQL transactions. -type TxOption func(*sql.TxOptions) - -func OptReadOnlyTx() TxOption { - return func(opts *sql.TxOptions) { - opts.ReadOnly = true - } -} - -func SqlTransaction(ctx context.Context, rdb *sql.DB, lggr logger.Logger, fn func(tx *sqlx.Tx) error, opts ...TxOption) (err error) { - db := WrapDbWithSqlx(rdb) - wrapFn := func(q Queryer) error { - tx, ok := q.(*sqlx.Tx) - if !ok { - panic(fmt.Sprintf("expected q to be %T but got %T", tx, q)) - } - return fn(tx) - } - return sqlxTransactionQ(ctx, db, lggr, wrapFn, opts...) -} - -// txBeginner can be a db or a conn, anything that implements BeginTxx -type txBeginner interface { - BeginTxx(context.Context, *sql.TxOptions) (*sqlx.Tx, error) -} - -func sqlxTransactionQ(ctx context.Context, db txBeginner, lggr logger.Logger, fn func(q Queryer) error, opts ...TxOption) (err error) { - var txOpts sql.TxOptions - for _, o := range opts { - o(&txOpts) - } - - var tx *sqlx.Tx - tx, err = db.BeginTxx(ctx, &txOpts) - if err != nil { - return errors.Wrap(err, "failed to begin transaction") - } - - defer func() { - if p := recover(); p != nil { - sentry.CurrentHub().Recover(p) - sentry.Flush(corelogger.SentryFlushDeadline) - - // A panic occurred, rollback and repanic - lggr.Errorf("Panic in transaction, rolling back: %s", p) - done := make(chan struct{}) - go func() { - if rerr := tx.Rollback(); rerr != nil { - lggr.Errorf("Failed to rollback on panic: %s", rerr) - } - close(done) - }() - select { - case <-done: - panic(p) - case <-time.After(10 * time.Second): - panic(fmt.Sprintf("panic in transaction; aborting rollback that took longer than 10s: %s", p)) - } - } else if err != nil { - lggr.Warnf("Error in transaction, rolling back: %s", err) - // An error occurred, rollback and return error - if rerr := tx.Rollback(); rerr != nil { - err = multierr.Combine(err, errors.WithStack(rerr)) - } - } else { - // All good! Time to commit. - err = errors.WithStack(tx.Commit()) - } - }() - - err = fn(tx) - - return -} diff --git a/core/services/pg/utils.go b/core/services/pg/utils.go deleted file mode 100644 index eb53c261296..00000000000 --- a/core/services/pg/utils.go +++ /dev/null @@ -1,50 +0,0 @@ -package pg - -import ( - "database/sql/driver" - "strconv" - "time" -) - -const ( - // DefaultQueryTimeout is a reasonable upper bound for how long a SQL query should take. - // The configured value should be used instead of this if possible. - DefaultQueryTimeout = 10 * time.Second - // longQueryTimeout is a bigger upper bound for how long a SQL query should take - longQueryTimeout = 1 * time.Minute -) - -var _ driver.Valuer = Limit(-1) - -// Limit is a helper driver.Valuer for LIMIT queries which uses nil/NULL for negative values. -type Limit int - -func (l Limit) String() string { - if l < 0 { - return "NULL" - } - return strconv.Itoa(int(l)) -} - -func (l Limit) Value() (driver.Value, error) { - if l < 0 { - return nil, nil - } - return l, nil -} - -var _ QConfig = &qConfig{} - -// qConfig implements pg.QCOnfig -type qConfig struct { - logSQL bool - defaultQueryTimeout time.Duration -} - -func NewQConfig(logSQL bool) QConfig { - return &qConfig{logSQL, DefaultQueryTimeout} -} - -func (p *qConfig) LogSQL() bool { return p.logSQL } - -func (p *qConfig) DefaultQueryTimeout() time.Duration { return p.defaultQueryTimeout } diff --git a/core/services/pipeline/helpers_test.go b/core/services/pipeline/helpers_test.go index 0bbdef7a7f2..97d81f56f74 100644 --- a/core/services/pipeline/helpers_test.go +++ b/core/services/pipeline/helpers_test.go @@ -5,7 +5,6 @@ import ( "github.com/google/uuid" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" ) @@ -65,4 +64,4 @@ func (t *ETHTxTask) HelperSetDependencies(legacyChains legacyevm.LegacyChainCont t.jobType = jobType } -func (o *orm) Prune(ds sqlutil.DataSource, pipelineSpecID int32) { o.prune(ds, pipelineSpecID) } +func (o *orm) Prune(pipelineSpecID int32) { o.prune(o.ds, pipelineSpecID) } diff --git a/core/services/pipeline/mocks/orm.go b/core/services/pipeline/mocks/orm.go index 2fa6d8681e8..9bd5ddfbdea 100644 --- a/core/services/pipeline/mocks/orm.go +++ b/core/services/pipeline/mocks/orm.go @@ -58,9 +58,9 @@ func (_m *ORM) CreateRun(ctx context.Context, run *pipeline.Run) error { return r0 } -// CreateSpec provides a mock function with given fields: ctx, ds, _a2, maxTaskTimeout -func (_m *ORM) CreateSpec(ctx context.Context, ds pipeline.CreateDataSource, _a2 pipeline.Pipeline, maxTaskTimeout models.Interval) (int32, error) { - ret := _m.Called(ctx, ds, _a2, maxTaskTimeout) +// CreateSpec provides a mock function with given fields: ctx, _a1, maxTaskTimeout +func (_m *ORM) CreateSpec(ctx context.Context, _a1 pipeline.Pipeline, maxTaskTimeout models.Interval) (int32, error) { + ret := _m.Called(ctx, _a1, maxTaskTimeout) if len(ret) == 0 { panic("no return value specified for CreateSpec") @@ -68,17 +68,17 @@ func (_m *ORM) CreateSpec(ctx context.Context, ds pipeline.CreateDataSource, _a2 var r0 int32 var r1 error - if rf, ok := ret.Get(0).(func(context.Context, pipeline.CreateDataSource, pipeline.Pipeline, models.Interval) (int32, error)); ok { - return rf(ctx, ds, _a2, maxTaskTimeout) + if rf, ok := ret.Get(0).(func(context.Context, pipeline.Pipeline, models.Interval) (int32, error)); ok { + return rf(ctx, _a1, maxTaskTimeout) } - if rf, ok := ret.Get(0).(func(context.Context, pipeline.CreateDataSource, pipeline.Pipeline, models.Interval) int32); ok { - r0 = rf(ctx, ds, _a2, maxTaskTimeout) + if rf, ok := ret.Get(0).(func(context.Context, pipeline.Pipeline, models.Interval) int32); ok { + r0 = rf(ctx, _a1, maxTaskTimeout) } else { r0 = ret.Get(0).(int32) } - if rf, ok := ret.Get(1).(func(context.Context, pipeline.CreateDataSource, pipeline.Pipeline, models.Interval) error); ok { - r1 = rf(ctx, ds, _a2, maxTaskTimeout) + if rf, ok := ret.Get(1).(func(context.Context, pipeline.Pipeline, models.Interval) error); ok { + r1 = rf(ctx, _a1, maxTaskTimeout) } else { r1 = ret.Error(1) } diff --git a/core/services/pipeline/orm.go b/core/services/pipeline/orm.go index 3bebfb8cbad..0a96a7e08d5 100644 --- a/core/services/pipeline/orm.go +++ b/core/services/pipeline/orm.go @@ -11,8 +11,6 @@ import ( "github.com/google/uuid" "github.com/pkg/errors" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" @@ -81,8 +79,7 @@ type CreateDataSource interface { type ORM interface { services.Service - // ds is optional and to be removed after completing https://smartcontract-it.atlassian.net/browse/BCF-2978 - CreateSpec(ctx context.Context, ds CreateDataSource, pipeline Pipeline, maxTaskTimeout models.Interval) (int32, error) + CreateSpec(ctx context.Context, pipeline Pipeline, maxTaskTimeout models.Interval) (int32, error) CreateRun(ctx context.Context, run *Run) (err error) InsertRun(ctx context.Context, run *Run) error DeleteRun(ctx context.Context, id int64) error @@ -163,6 +160,9 @@ func (o *orm) Transact(ctx context.Context, fn func(ORM) error) error { return sqlutil.Transact(ctx, func(tx sqlutil.DataSource) ORM { return o.withDataSource(tx) }, o.ds, nil, func(tx ORM) error { + if err := tx.Start(ctx); err != nil { + return fmt.Errorf("failed to start tx orm: %w", err) + } defer func() { if err := tx.Close(); err != nil { o.lggr.Warnw("Error closing temporary transactional ORM", "err", err) @@ -191,14 +191,11 @@ func (o *orm) transact(ctx context.Context, fn func(*orm) error) error { return sqlutil.Transact(ctx, o.withDataSource, o.ds, nil, fn) } -func (o *orm) CreateSpec(ctx context.Context, ds CreateDataSource, pipeline Pipeline, maxTaskDuration models.Interval) (id int32, err error) { +func (o *orm) CreateSpec(ctx context.Context, pipeline Pipeline, maxTaskDuration models.Interval) (id int32, err error) { sql := `INSERT INTO pipeline_specs (dot_dag_source, max_task_duration, created_at) VALUES ($1, $2, NOW()) RETURNING id;` - if ds == nil { - ds = o.ds - } - err = ds.GetContext(ctx, &id, sql, pipeline.Source, maxTaskDuration) + err = o.ds.GetContext(ctx, &id, sql, pipeline.Source, maxTaskDuration) return id, errors.WithStack(err) } @@ -254,13 +251,13 @@ func (o *orm) StoreRun(ctx context.Context, run *Run) (restart bool, err error) // Lock the current run. This prevents races with /v2/resume sql := `SELECT id FROM pipeline_runs WHERE id = $1 FOR UPDATE;` if _, err = tx.ds.ExecContext(ctx, sql, run.ID); err != nil { - return errors.Wrap(err, "StoreRun") + return fmt.Errorf("failed to select pipeline run %d: %w", run.ID, err) } taskRuns := []TaskRun{} // Reload task runs, we want to check for any changes while the run was ongoing if err = tx.ds.SelectContext(ctx, &taskRuns, `SELECT * FROM pipeline_task_runs WHERE pipeline_run_id = $1`, run.ID); err != nil { - return errors.Wrap(err, "StoreRun") + return fmt.Errorf("failed to select piepline task run %d: %w", run.ID, err) } // Construct a temporary run so we can use r.ByDotID @@ -287,17 +284,17 @@ func (o *orm) StoreRun(ctx context.Context, run *Run) (restart bool, err error) // Suspend the run run.State = RunStatusSuspended if _, err = tx.ds.NamedExecContext(ctx, `UPDATE pipeline_runs SET state = :state WHERE id = :id`, run); err != nil { - return errors.Wrap(err, "StoreRun") + return fmt.Errorf("failed to update pipeline run %d to %s: %w", run.ID, run.State, err) } } else { defer o.prune(tx.ds, run.PruningKey) // Simply finish the run, no need to do any sort of locking if run.Outputs.Val == nil || len(run.FatalErrors)+len(run.AllErrors) == 0 { - return errors.Errorf("run must have both Outputs and Errors, got Outputs: %#v, FatalErrors: %#v, AllErrors: %#v", run.Outputs.Val, run.FatalErrors, run.AllErrors) + return fmt.Errorf("run must have both Outputs and Errors, got Outputs: %#v, FatalErrors: %#v, AllErrors: %#v", run.Outputs.Val, run.FatalErrors, run.AllErrors) } sql := `UPDATE pipeline_runs SET state = :state, finished_at = :finished_at, all_errors= :all_errors, fatal_errors= :fatal_errors, outputs = :outputs WHERE id = :id` if _, err = tx.ds.NamedExecContext(ctx, sql, run); err != nil { - return errors.Wrap(err, "StoreRun") + return fmt.Errorf("failed to update pipeline run %d: %w", run.ID, err) } } @@ -309,18 +306,15 @@ func (o *orm) StoreRun(ctx context.Context, run *Run) (restart bool, err error) RETURNING *; ` - // NOTE: can't use Select() to auto scan because we're using NamedQuery, - // sqlx.Named + Select is possible but it's about the same amount of code - var rows *sqlx.Rows - rows, err = sqlx.NamedQueryContext(ctx, tx.ds, sql, run.PipelineTaskRuns) + taskRuns := []TaskRun{} + query, args, err := tx.ds.BindNamed(sql, run.PipelineTaskRuns) if err != nil { - return errors.Wrap(err, "StoreRun") + return fmt.Errorf("failed to prepare named query: %w", err) } - taskRuns := []TaskRun{} - if err = sqlx.StructScan(rows, &taskRuns); err != nil { - return errors.Wrap(err, "StoreRun") + err = tx.ds.SelectContext(ctx, &taskRuns, query, args...) + if err != nil { + return fmt.Errorf("failed to insert pipeline task runs: %w", err) } - // replace with new task run data run.PipelineTaskRuns = taskRuns return nil }) @@ -383,19 +377,18 @@ VALUES (:pipeline_spec_id, :pruning_key, :meta, :all_errors, :fatal_errors, :inputs, :outputs, :created_at, :finished_at, :state) RETURNING id ` - rows, errQ := sqlx.NamedQueryContext(ctx, tx.ds, pipelineRunsQuery, runs) - if errQ != nil { - return errors.Wrap(errQ, "inserting finished pipeline runs") - } - defer rows.Close() var runIDs []int64 - for rows.Next() { + err := sqlutil.NamedQueryContext(ctx, tx.ds, pipelineRunsQuery, runs, func(row sqlutil.RowScanner) error { var runID int64 - if errS := rows.Scan(&runID); errS != nil { + if errS := row.Scan(&runID); errS != nil { return errors.Wrap(errS, "scanning pipeline runs id row") } runIDs = append(runIDs, runID) + return nil + }) + if err != nil { + return errors.Wrap(err, "inserting finished pipeline runs") } pruningKeysm := make(map[int32]struct{}) @@ -717,13 +710,13 @@ const syncLimit = 1000 // // Note this does not guarantee the pipeline_runs table is kept to exactly the // max length, rather that it doesn't excessively larger than it. -func (o *orm) prune(ds sqlutil.DataSource, jobID int32) { +func (o *orm) prune(tx sqlutil.DataSource, jobID int32) { if jobID == 0 { o.lggr.Panic("expected a non-zero job ID") } // For small maxSuccessfulRuns its fast enough to prune every time if o.maxSuccessfulRuns < syncLimit { - o.execPrune(o.ctx, ds, jobID) + o.withDataSource(tx).execPrune(o.ctx, jobID) return } // for large maxSuccessfulRuns we do it async on a sampled basis @@ -736,11 +729,11 @@ func (o *orm) prune(ds sqlutil.DataSource, jobID int32) { go func() { o.lggr.Debugw("Pruning runs", "jobID", jobID, "count", val, "every", every, "maxSuccessfulRuns", o.maxSuccessfulRuns) defer o.wg.Done() - // Must not use ds here since it's async and the transaction - // could be stale ctx, cancel := context.WithTimeout(sqlutil.WithoutDefaultTimeout(o.ctx), time.Minute) defer cancel() - o.execPrune(ctx, o.ds, jobID) + + // Must not use tx here since it could be stale by the time we execute async. + o.execPrune(ctx, jobID) }() }) if !ok { @@ -750,8 +743,8 @@ func (o *orm) prune(ds sqlutil.DataSource, jobID int32) { } } -func (o *orm) execPrune(ctx context.Context, ds sqlutil.DataSource, jobID int32) { - res, err := ds.ExecContext(o.ctx, `DELETE FROM pipeline_runs WHERE pruning_key = $1 AND state = $2 AND id NOT IN ( +func (o *orm) execPrune(ctx context.Context, jobID int32) { + res, err := o.ds.ExecContext(o.ctx, `DELETE FROM pipeline_runs WHERE pruning_key = $1 AND state = $2 AND id NOT IN ( SELECT id FROM pipeline_runs WHERE pruning_key = $1 AND state = $2 ORDER BY id DESC @@ -769,7 +762,7 @@ LIMIT $3 if rowsAffected == 0 { // check the spec still exists and garbage collect if necessary var exists bool - if err := ds.GetContext(ctx, &exists, `SELECT EXISTS(SELECT ps.* FROM pipeline_specs ps JOIN job_pipeline_specs jps ON (ps.id=jps.pipeline_spec_id) WHERE jps.job_id = $1)`, jobID); err != nil { + if err := o.ds.GetContext(ctx, &exists, `SELECT EXISTS(SELECT ps.* FROM pipeline_specs ps JOIN job_pipeline_specs jps ON (ps.id=jps.pipeline_spec_id) WHERE jps.job_id = $1)`, jobID); err != nil { o.lggr.Errorw("Failed check existence of pipeline_spec while pruning runs", "err", err, "jobID", jobID) return } diff --git a/core/services/pipeline/orm_test.go b/core/services/pipeline/orm_test.go index bba928534ba..6ff32e15cc7 100644 --- a/core/services/pipeline/orm_test.go +++ b/core/services/pipeline/orm_test.go @@ -1,6 +1,7 @@ package pipeline_test import ( + "context" "testing" "time" @@ -12,6 +13,7 @@ import ( "github.com/jmoiron/sqlx" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" "github.com/smartcontractkit/chainlink-common/pkg/utils/jsonserializable" @@ -25,41 +27,34 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/store/models" ) -type ormconfig struct { - pg.QConfig -} - -func (ormconfig) JobPipelineMaxSuccessfulRuns() uint64 { return 123456 } - type testOnlyORM interface { pipeline.ORM - AddJobPipelineSpecWithoutConstraints(jobID, pipelineSpecID int32) error + AddJobPipelineSpecWithoutConstraints(ctx context.Context, jobID, pipelineSpecID int32) error } type testORM struct { pipeline.ORM - db *sqlx.DB + ds sqlutil.DataSource } -func (torm *testORM) AddJobPipelineSpecWithoutConstraints(jobID, pipelineSpecID int32) error { - _, err := torm.db.Exec(`SET CONSTRAINTS fk_job_pipeline_spec_job DEFERRED`) +func (torm *testORM) AddJobPipelineSpecWithoutConstraints(ctx context.Context, jobID, pipelineSpecID int32) error { + _, err := torm.ds.ExecContext(ctx, `SET CONSTRAINTS fk_job_pipeline_spec_job DEFERRED`) if err != nil { return err } - _, err = torm.db.Exec(`INSERT INTO job_pipeline_specs (job_id,pipeline_spec_id, is_primary) VALUES ($1, $2, false)`, jobID, pipelineSpecID) + _, err = torm.ds.ExecContext(ctx, `INSERT INTO job_pipeline_specs (job_id,pipeline_spec_id, is_primary) VALUES ($1, $2, false)`, jobID, pipelineSpecID) if err != nil { return err } return nil } -func newTestORM(orm pipeline.ORM, db *sqlx.DB) testOnlyORM { - return &testORM{ORM: orm, db: db} +func newTestORM(orm pipeline.ORM, ds sqlutil.DataSource) testOnlyORM { + return &testORM{ORM: orm, ds: ds} } func setupORM(t *testing.T, heavy bool) (db *sqlx.DB, orm pipeline.ORM, jorm job.ORM) { @@ -70,14 +65,12 @@ func setupORM(t *testing.T, heavy bool) (db *sqlx.DB, orm pipeline.ORM, jorm job } else { db = pgtest.NewSqlxDB(t) } - cfg := ormconfig{pgtest.NewQConfig(true)} - orm = pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipelineMaxSuccessfulRuns()) - config := configtest.NewTestGeneralConfig(t) + orm = pipeline.NewORM(db, logger.TestLogger(t), 123456) lggr := logger.TestLogger(t) keyStore := cltest.NewKeyStore(t, db) bridgeORM := bridges.NewORM(db) - jorm = job.NewORM(db, orm, bridgeORM, keyStore, lggr, config.Database()) + jorm = job.NewORM(db, orm, bridgeORM, keyStore, lggr) return } @@ -103,7 +96,7 @@ func Test_PipelineORM_CreateSpec(t *testing.T) { Source: source, } - id, err := orm.CreateSpec(ctx, nil, p, maxTaskDuration) + id, err := orm.CreateSpec(ctx, p, maxTaskDuration) require.NoError(t, err) actual := pipeline.Spec{} @@ -171,7 +164,7 @@ answer2 [type=bridge name=election_winner index=1]; DotDagSource: s, }, } - err := jobORM.CreateJob(&jb) + err := jobORM.CreateJob(ctx, &jb) require.NoError(t, err) run := &pipeline.Run{ @@ -274,7 +267,7 @@ answer2 [type=bridge name=election_winner index=1]; DotDagSource: s, }, } - err := jorm.CreateJob(&jb) + err := jorm.CreateJob(ctx, &jb) require.NoError(t, err) spec := pipeline.Spec{ DotDagSource: s, @@ -665,7 +658,7 @@ func Test_GetUnfinishedRuns_Keepers(t *testing.T) { porm := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgeORM := bridges.NewORM(db) - jorm := job.NewORM(db, porm, bridgeORM, keyStore, lggr, config.Database()) + jorm := job.NewORM(db, porm, bridgeORM, keyStore, lggr) defer func() { assert.NoError(t, jorm.Close()) }() timestamp := time.Now() @@ -689,7 +682,7 @@ func Test_GetUnfinishedRuns_Keepers(t *testing.T) { MaxTaskDuration: models.Interval(1 * time.Minute), } - err := jorm.CreateJob(&keeperJob) + err := jorm.CreateJob(ctx, &keeperJob) require.NoError(t, err) require.Equal(t, job.Keeper, keeperJob.Type) @@ -768,7 +761,7 @@ func Test_GetUnfinishedRuns_DirectRequest(t *testing.T) { porm := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgeORM := bridges.NewORM(db) - jorm := job.NewORM(db, porm, bridgeORM, keyStore, lggr, config.Database()) + jorm := job.NewORM(db, porm, bridgeORM, keyStore, lggr) defer func() { assert.NoError(t, jorm.Close()) }() timestamp := time.Now() @@ -791,7 +784,7 @@ func Test_GetUnfinishedRuns_DirectRequest(t *testing.T) { MaxTaskDuration: models.Interval(1 * time.Minute), } - err := jorm.CreateJob(&drJob) + err := jorm.CreateJob(ctx, &drJob) require.NoError(t, err) require.Equal(t, job.DirectRequest, drJob.Type) @@ -865,13 +858,13 @@ func Test_Prune(t *testing.T) { ps1 := cltest.MustInsertPipelineSpec(t, db) // We need a job_pipeline_specs entry to test the pruning mechanism - err := torm.AddJobPipelineSpecWithoutConstraints(ps1.ID, ps1.ID) + err := torm.AddJobPipelineSpecWithoutConstraints(testutils.Context(t), ps1.ID, ps1.ID) require.NoError(t, err) jobID := ps1.ID t.Run("when there are no runs to prune, does nothing", func(t *testing.T) { - porm.Prune(db, jobID) + porm.Prune(jobID) // no error logs; it did nothing assert.Empty(t, observed.All()) @@ -907,7 +900,7 @@ func Test_Prune(t *testing.T) { cltest.MustInsertPipelineRunWithStatus(t, db, ps2.ID, pipeline.RunStatusSuspended, jobID2) } - porm.Prune(db, jobID2) + porm.Prune(jobID2) cnt := pgtest.MustCount(t, db, "SELECT count(*) FROM pipeline_runs WHERE pipeline_spec_id = $1 AND state = $2", ps1.ID, pipeline.RunStatusCompleted) assert.Equal(t, cnt, 20) diff --git a/core/services/pipeline/runner.go b/core/services/pipeline/runner.go index 862d2f49178..2de27b3d008 100644 --- a/core/services/pipeline/runner.go +++ b/core/services/pipeline/runner.go @@ -661,7 +661,7 @@ func (r *runner) Run(ctx context.Context, run *Run, l logger.Logger, saveSuccess } if err = r.orm.InsertFinishedRun(ctx, run, saveSuccessfulTaskRuns); err != nil { - return false, pkgerrors.Wrapf(err, "error storing run for spec ID %v", run.PipelineSpec.ID) + return false, pkgerrors.Wrapf(err, "error inserting finished run for spec ID %v", run.PipelineSpec.ID) } } diff --git a/core/services/pipeline/runner_test.go b/core/services/pipeline/runner_test.go index e086d5297ef..44d7acadd27 100644 --- a/core/services/pipeline/runner_test.go +++ b/core/services/pipeline/runner_test.go @@ -33,7 +33,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline/mocks" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -42,14 +41,10 @@ import ( ) func newRunner(t testing.TB, db *sqlx.DB, bridgeORM bridges.ORM, cfg chainlink.GeneralConfig) (pipeline.Runner, *mocks.ORM) { - lggr := logger.TestLogger(t) ethKeyStore := cltest.NewKeyStore(t, db).Eth() relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, KeyStore: ethKeyStore}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) orm := mocks.NewORM(t) - q := pg.NewQ(db, lggr, cfg.Database()) - - orm.On("GetQ").Return(q).Maybe() c := clhttptest.NewTestLocalOnlyHTTPClient() r := pipeline.NewRunner(orm, bridgeORM, cfg.JobPipeline(), cfg.WebServer(), legacyChains, ethKeyStore, nil, logger.TestLogger(t), c, c) return r, orm @@ -250,8 +245,7 @@ func Test_PipelineRunner_ExecuteTaskRunsWithVars(t *testing.T) { "times": "1000000000000000000", }, }, - }, - cfg.Database()) + }) defer ds1.Close() btORM.On("FindBridge", mock.Anything, bridge.Name).Return(bridge, nil).Once() @@ -269,7 +263,7 @@ func Test_PipelineRunner_ExecuteTaskRunsWithVars(t *testing.T) { defer ds4.Close() // 3. Setup final bridge task - submit, submitBt := makeBridge(t, db, expectedRequestSubmit, map[string]interface{}{"ok": true}, cfg.Database()) + submit, submitBt := makeBridge(t, db, expectedRequestSubmit, map[string]interface{}{"ok": true}) defer submit.Close() btORM.On("FindBridge", mock.Anything, submitBt.Name).Return(submitBt, nil).Once() @@ -419,10 +413,7 @@ func Test_PipelineRunner_HandleFaults(t *testing.T) { // but a sufficient number of them still complete within the desired time frame // and so we can still obtain a median. db := pgtest.NewSqlxDB(t) - orm := mocks.NewORM(t) - q := pg.NewQ(db, logger.TestLogger(t), configtest.NewTestGeneralConfig(t).Database()) - orm.On("GetQ").Return(q).Maybe() m1 := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { time.Sleep(100 * time.Millisecond) res.WriteHeader(http.StatusOK) @@ -472,8 +463,7 @@ func Test_PipelineRunner_HandleFaultsPersistRun(t *testing.T) { db := pgtest.NewSqlxDB(t) orm := mocks.NewORM(t) btORM := bridgesMocks.NewORM(t) - q := pg.NewQ(db, logger.TestLogger(t), configtest.NewTestGeneralConfig(t).Database()) - orm.On("GetQ").Return(q).Maybe() + orm.On("InsertFinishedRun", mock.Anything, mock.Anything, mock.Anything). Run(func(args mock.Arguments) { args.Get(1).(*pipeline.Run).ID = 1 @@ -513,8 +503,7 @@ func Test_PipelineRunner_ExecuteAndInsertFinishedRun_SavingTheSpec(t *testing.T) db := pgtest.NewSqlxDB(t) orm := mocks.NewORM(t) btORM := bridgesMocks.NewORM(t) - q := pg.NewQ(db, logger.TestLogger(t), configtest.NewTestGeneralConfig(t).Database()) - orm.On("GetQ").Return(q).Maybe() + orm.On("InsertFinishedRunWithSpec", mock.Anything, mock.Anything, mock.Anything). Run(func(args mock.Arguments) { args.Get(1).(*pipeline.Run).ID = 1 diff --git a/core/services/pipeline/task.bridge_test.go b/core/services/pipeline/task.bridge_test.go index 029c6c78ca8..e95aef4984c 100644 --- a/core/services/pipeline/task.bridge_test.go +++ b/core/services/pipeline/task.bridge_test.go @@ -29,7 +29,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline/internal/eautils" "github.com/smartcontractkit/chainlink/v2/core/store/models" @@ -217,7 +216,7 @@ func TestBridgeTask_Happy(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -259,7 +258,7 @@ func TestBridgeTask_HandlesIntermittentFailure(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) result, runInfo := task.Run(testutils.Context(t), logger.TestLogger(t), @@ -300,18 +299,19 @@ func TestBridgeTask_HandlesIntermittentFailure(t *testing.T) { func TestBridgeTask_DoesNotReturnStaleResults(t *testing.T) { t.Parallel() - db := pgtest.NewSqlxDB(t) + ctx := testutils.Context(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.WebServer.BridgeCacheTTL = commonconfig.MustNewDuration(30 * time.Second) }) - queryer := pg.NewQ(db, logger.TestLogger(t), cfg.Database()) + s1 := httptest.NewServer(fakeIntermittentlyFailingPriceResponder(t, utils.MustUnmarshalToMap(btcUSDPairing), decimal.NewFromInt(9700), "", nil)) defer s1.Close() feedURL, err := url.ParseRequestURI(s1.URL) require.NoError(t, err) + db := pgtest.NewSqlxDB(t) orm := bridges.NewORM(db) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{URL: feedURL.String()}) @@ -322,12 +322,12 @@ func TestBridgeTask_DoesNotReturnStaleResults(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) // Insert entry 1m in the past, stale value, should not be used in case of EA failure. - err = queryer.ExecQ(`INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) + _, err = db.ExecContext(ctx, `INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) VALUES($1, $2, $3, $4) ON CONFLICT ON CONSTRAINT bridge_last_value_pkey DO UPDATE SET value = $3, finished_at = $4;`, task.DotID(), specID, big.NewInt(9700).Bytes(), time.Now().Add(-1*time.Minute)) require.NoError(t, err) @@ -348,7 +348,7 @@ func TestBridgeTask_DoesNotReturnStaleResults(t *testing.T) { require.Nil(t, result2.Value) // Insert entry 10s in the past, under 30 seconds and should be used in case of failure. - err = queryer.ExecQ(`INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) + _, err = db.ExecContext(ctx, `INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) VALUES($1, $2, $3, $4) ON CONFLICT ON CONSTRAINT bridge_last_value_pkey DO UPDATE SET value = $3, finished_at = $4;`, task.DotID(), specID, big.NewInt(9700).Bytes(), time.Now().Add(-10*time.Second)) require.NoError(t, err) @@ -398,7 +398,7 @@ func TestBridgeTask_DoesNotReturnStaleResults(t *testing.T) { task2.HelperSetDependencies(cfg2.JobPipeline(), cfg2.WebServer(), orm, specID, uuid.UUID{}, c) // Insert entry 32m in the past, under cacheTTL of 35m but more than stalenessCap of 30m. - err = queryer.ExecQ(`INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) + _, err = db.ExecContext(ctx, `INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) VALUES($1, $2, $3, $4) ON CONFLICT ON CONSTRAINT bridge_last_value_pkey DO UPDATE SET value = $3, finished_at = $4;`, task2.DotID(), specID, big.NewInt(9700).Bytes(), time.Now().Add(-32*time.Minute)) require.NoError(t, err) @@ -420,7 +420,7 @@ func TestBridgeTask_DoesNotReturnStaleResults(t *testing.T) { require.Nil(t, result2.Value) // Insert entry 25m in the past, under stalenessCap - err = queryer.ExecQ(`INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) + _, err = db.ExecContext(ctx, `INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) VALUES($1, $2, $3, $4) ON CONFLICT ON CONSTRAINT bridge_last_value_pkey DO UPDATE SET value = $3, finished_at = $4;`, task2.DotID(), specID, big.NewInt(9700).Bytes(), time.Now().Add(-25*time.Minute)) require.NoError(t, err) @@ -482,7 +482,7 @@ func TestBridgeTask_AsyncJobPendingState(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, id, c) @@ -660,7 +660,7 @@ func TestBridgeTask_Variables(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -729,7 +729,7 @@ func TestBridgeTask_Meta(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -783,7 +783,7 @@ func TestBridgeTask_IncludeInputAtKey(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -839,7 +839,7 @@ func TestBridgeTask_ErrorMessage(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -878,7 +878,7 @@ func TestBridgeTask_OnlyErrorMessage(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -903,7 +903,7 @@ func TestBridgeTask_ErrorIfBridgeMissing(t *testing.T) { c := clhttptest.NewTestLocalOnlyHTTPClient() orm := bridges.NewORM(db) trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -993,7 +993,7 @@ func TestBridgeTask_Headers(t *testing.T) { c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -1015,7 +1015,7 @@ func TestBridgeTask_Headers(t *testing.T) { c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -1037,7 +1037,7 @@ func TestBridgeTask_Headers(t *testing.T) { c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) @@ -1052,6 +1052,7 @@ func TestBridgeTask_Headers(t *testing.T) { func TestBridgeTask_AdapterResponseStatusFailure(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -1062,7 +1063,6 @@ func TestBridgeTask_AdapterResponseStatusFailure(t *testing.T) { Data: adapterResponseData{Result: &decimal.Zero}, } - queryer := pg.NewQ(db, logger.TestLogger(t), cfg.Database()) s1 := httptest.NewServer( http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { err := json.NewEncoder(w).Encode(testAdapterResponse) @@ -1083,12 +1083,12 @@ func TestBridgeTask_AdapterResponseStatusFailure(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(ctx, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) // Insert entry 1m in the past, stale value, should not be used in case of EA failure. - err = queryer.ExecQ(`INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) + _, err = db.ExecContext(ctx, `INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) VALUES($1, $2, $3, $4) ON CONFLICT ON CONSTRAINT bridge_last_value_pkey DO UPDATE SET value = $3, finished_at = $4;`, task.DotID(), specID, big.NewInt(9700).Bytes(), time.Now()) require.NoError(t, err) @@ -1105,7 +1105,7 @@ func TestBridgeTask_AdapterResponseStatusFailure(t *testing.T) { // expect all external adapter response status failures to be served from the cache testAdapterResponse.SetStatusCode(http.StatusBadRequest) - result, runInfo := task.Run(testutils.Context(t), logger.TestLogger(t), vars, nil) + result, runInfo := task.Run(ctx, logger.TestLogger(t), vars, nil) require.NoError(t, result.Error) require.NotNil(t, result.Value) @@ -1114,7 +1114,7 @@ func TestBridgeTask_AdapterResponseStatusFailure(t *testing.T) { testAdapterResponse.SetStatusCode(http.StatusOK) testAdapterResponse.SetProviderStatusCode(http.StatusBadRequest) - result, runInfo = task.Run(testutils.Context(t), logger.TestLogger(t), vars, nil) + result, runInfo = task.Run(ctx, logger.TestLogger(t), vars, nil) require.NoError(t, result.Error) require.NotNil(t, result.Value) @@ -1124,7 +1124,7 @@ func TestBridgeTask_AdapterResponseStatusFailure(t *testing.T) { testAdapterResponse.SetStatusCode(http.StatusOK) testAdapterResponse.SetProviderStatusCode(http.StatusOK) testAdapterResponse.SetError("some error") - result, runInfo = task.Run(testutils.Context(t), logger.TestLogger(t), vars, nil) + result, runInfo = task.Run(ctx, logger.TestLogger(t), vars, nil) require.NoError(t, result.Error) require.NotNil(t, result.Value) @@ -1132,7 +1132,7 @@ func TestBridgeTask_AdapterResponseStatusFailure(t *testing.T) { require.False(t, runInfo.IsPending) testAdapterResponse.SetStatusCode(http.StatusInternalServerError) - result, runInfo = task.Run(testutils.Context(t), logger.TestLogger(t), vars, nil) + result, runInfo = task.Run(ctx, logger.TestLogger(t), vars, nil) require.NoError(t, result.Error) require.NotNil(t, result.Value) diff --git a/core/services/pipeline/task.http_test.go b/core/services/pipeline/task.http_test.go index 6264d1e591b..4098ce50d2a 100644 --- a/core/services/pipeline/task.http_test.go +++ b/core/services/pipeline/task.http_test.go @@ -177,7 +177,7 @@ func TestHTTPTask_Variables(t *testing.T) { } c := clhttptest.NewTestLocalOnlyHTTPClient() trORM := pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipeline().MaxSuccessfulRuns()) - specID, err := trORM.CreateSpec(testutils.Context(t), nil, pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) + specID, err := trORM.CreateSpec(testutils.Context(t), pipeline.Pipeline{}, *models.NewInterval(5 * time.Minute)) require.NoError(t, err) task.HelperSetDependencies(cfg.JobPipeline(), cfg.WebServer(), orm, specID, uuid.UUID{}, c) diff --git a/core/services/pipeline/test_helpers_test.go b/core/services/pipeline/test_helpers_test.go index fc87942e073..d890afc33df 100644 --- a/core/services/pipeline/test_helpers_test.go +++ b/core/services/pipeline/test_helpers_test.go @@ -13,7 +13,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/jmoiron/sqlx" @@ -39,7 +38,7 @@ func fakeExternalAdapter(t *testing.T, expectedRequest, response interface{}) ht }) } -func makeBridge(t *testing.T, db *sqlx.DB, expectedRequest, response interface{}, cfg pg.QConfig) (*httptest.Server, bridges.BridgeType) { +func makeBridge(t *testing.T, db *sqlx.DB, expectedRequest, response interface{}) (*httptest.Server, bridges.BridgeType) { t.Helper() server := httptest.NewServer(fakeExternalAdapter(t, expectedRequest, response)) diff --git a/core/services/promreporter/prom_reporter.go b/core/services/promreporter/prom_reporter.go index a302a6fa220..92e674aac44 100644 --- a/core/services/promreporter/prom_reporter.go +++ b/core/services/promreporter/prom_reporter.go @@ -2,12 +2,12 @@ package promreporter import ( "context" - "database/sql" "fmt" "math/big" "sync" "time" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" @@ -28,7 +28,7 @@ import ( type ( promReporter struct { services.StateMachine - db *sql.DB + ds sqlutil.DataSource chains legacyevm.LegacyChainContainer lggr logger.Logger backend PrometheusBackend @@ -92,7 +92,7 @@ func (defaultBackend) SetPipelineTaskRunsQueued(n int) { promPipelineRunsQueued.Set(float64(n)) } -func NewPromReporter(db *sql.DB, chainContainer legacyevm.LegacyChainContainer, lggr logger.Logger, opts ...interface{}) *promReporter { +func NewPromReporter(ds sqlutil.DataSource, chainContainer legacyevm.LegacyChainContainer, lggr logger.Logger, opts ...interface{}) *promReporter { var backend PrometheusBackend = defaultBackend{} period := 15 * time.Second for _, opt := range opts { @@ -106,7 +106,7 @@ func NewPromReporter(db *sql.DB, chainContainer legacyevm.LegacyChainContainer, chStop := make(chan struct{}) return &promReporter{ - db: db, + ds: ds, chains: chainContainer, lggr: lggr.Named("PromReporter"), backend: backend, @@ -242,7 +242,7 @@ func (pr *promReporter) reportMaxUnconfirmedBlocks(ctx context.Context, head *ev } func (pr *promReporter) reportPipelineRunStats(ctx context.Context) (err error) { - rows, err := pr.db.QueryContext(ctx, ` + rows, err := pr.ds.QueryContext(ctx, ` SELECT pipeline_run_id FROM pipeline_task_runs WHERE finished_at IS NULL `) if err != nil { diff --git a/core/services/promreporter/prom_reporter_test.go b/core/services/promreporter/prom_reporter_test.go index bb09b86df95..f17b4aafed2 100644 --- a/core/services/promreporter/prom_reporter_test.go +++ b/core/services/promreporter/prom_reporter_test.go @@ -48,7 +48,6 @@ func newLegacyChainContainer(t *testing.T, db *sqlx.DB) legacyevm.LegacyChainCon lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.FixtureChainID, db, lggr), ethClient, lggr, lpOpts) txm, err := txmgr.NewTxm( - db, db, evmConfig, evmConfig.GasEstimator(), @@ -72,7 +71,7 @@ func Test_PromReporter_OnNewLongestChain(t *testing.T) { db := pgtest.NewSqlxDB(t) backend := mocks.NewPrometheusBackend(t) - reporter := promreporter.NewPromReporter(db.DB, newLegacyChainContainer(t, db), logger.TestLogger(t), backend, 10*time.Millisecond) + reporter := promreporter.NewPromReporter(db, newLegacyChainContainer(t, db), logger.TestLogger(t), backend, 10*time.Millisecond) var subscribeCalls atomic.Int32 @@ -114,7 +113,7 @@ func Test_PromReporter_OnNewLongestChain(t *testing.T) { subscribeCalls.Add(1) }). Return() - reporter := promreporter.NewPromReporter(db.DB, newLegacyChainContainer(t, db), logger.TestLogger(t), backend, 10*time.Millisecond) + reporter := promreporter.NewPromReporter(db, newLegacyChainContainer(t, db), logger.TestLogger(t), backend, 10*time.Millisecond) servicetest.Run(t, reporter) etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) @@ -133,7 +132,7 @@ func Test_PromReporter_OnNewLongestChain(t *testing.T) { pgtest.MustExec(t, db, `SET CONSTRAINTS pipeline_task_runs_pipeline_run_id_fkey DEFERRED`) backend := mocks.NewPrometheusBackend(t) - reporter := promreporter.NewPromReporter(db.DB, newLegacyChainContainer(t, db), logger.TestLogger(t), backend, 10*time.Millisecond) + reporter := promreporter.NewPromReporter(db, newLegacyChainContainer(t, db), logger.TestLogger(t), backend, 10*time.Millisecond) cltest.MustInsertUnfinishedPipelineTaskRun(t, db, 1) cltest.MustInsertUnfinishedPipelineTaskRun(t, db, 1) diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index e9aaa7e0a8e..2f30d40e28d 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -11,7 +11,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" - "github.com/jmoiron/sqlx" pkgerrors "github.com/pkg/errors" "golang.org/x/exp/maps" @@ -35,7 +34,6 @@ import ( lloconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/llo/config" mercuryconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/mercury/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/functions" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury" mercuryutils "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/utils" @@ -71,13 +69,11 @@ func init() { var _ commontypes.Relayer = &Relayer{} //nolint:staticcheck type Relayer struct { - db *sqlx.DB // legacy: prefer to use ds instead ds sqlutil.DataSource chain legacyevm.Chain lggr logger.Logger ks CSAETHKeystore mercuryPool wsrpc.Pool - pgCfg pg.QConfig chainReader commontypes.ChainReader codec commontypes.Codec @@ -95,24 +91,16 @@ type CSAETHKeystore interface { } type RelayerOpts struct { - *sqlx.DB // legacy: prefer to use ds instead - DS sqlutil.DataSource - pg.QConfig + DS sqlutil.DataSource CSAETHKeystore MercuryPool wsrpc.Pool } func (c RelayerOpts) Validate() error { var err error - if c.DB == nil { - err = errors.Join(err, errors.New("nil DB")) - } if c.DS == nil { err = errors.Join(err, errors.New("nil DataSource")) } - if c.QConfig == nil { - err = errors.Join(err, errors.New("nil QConfig")) - } if c.CSAETHKeystore == nil { err = errors.Join(err, errors.New("nil Keystore")) } @@ -134,13 +122,11 @@ func NewRelayer(lggr logger.Logger, chain legacyevm.Chain, opts RelayerOpts) (*R lloORM := llo.NewORM(opts.DS, chain.ID()) cdcFactory := llo.NewChannelDefinitionCacheFactory(lggr, lloORM, chain.LogPoller()) return &Relayer{ - db: opts.DB, ds: opts.DS, chain: chain, lggr: lggr, ks: opts.CSAETHKeystore, mercuryPool: opts.MercuryPool, - pgCfg: opts.QConfig, cdcFactory: cdcFactory, lloORM: lloORM, mercuryORM: mercuryORM, @@ -637,7 +623,7 @@ func (r *Relayer) NewMedianProvider(rargs commontypes.RelayArgs, pargs commontyp func (r *Relayer) NewAutomationProvider(rargs commontypes.RelayArgs, pargs commontypes.PluginArgs) (commontypes.AutomationProvider, error) { lggr := r.lggr.Named("AutomationProvider").Named(rargs.ExternalJobID.String()) - ocr2keeperRelayer := NewOCR2KeeperRelayer(r.db, r.chain, lggr.Named("OCR2KeeperRelayer"), r.ks.Eth(), r.pgCfg) + ocr2keeperRelayer := NewOCR2KeeperRelayer(r.ds, r.chain, lggr.Named("OCR2KeeperRelayer"), r.ks.Eth()) return ocr2keeperRelayer.NewOCR2KeeperProvider(rargs, pargs) } diff --git a/core/services/relay/evm/evm_test.go b/core/services/relay/evm/evm_test.go index d53fe910bc3..ab60ff2a128 100644 --- a/core/services/relay/evm/evm_test.go +++ b/core/services/relay/evm/evm_test.go @@ -5,20 +5,13 @@ import ( "github.com/stretchr/testify/assert" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) func TestRelayerOpts_Validate(t *testing.T) { - cfg := configtest.NewTestGeneralConfig(t) type fields struct { - DB *sqlx.DB DS sqlutil.DataSource - QConfig pg.QConfig CSAETHKeystore evm.CSAETHKeystore } tests := []struct { @@ -29,33 +22,25 @@ func TestRelayerOpts_Validate(t *testing.T) { { name: "all invalid", fields: fields{ - DB: nil, DS: nil, - QConfig: nil, CSAETHKeystore: nil, }, - wantErrContains: `nil DB -nil DataSource -nil QConfig + wantErrContains: `nil DataSource nil Keystore`, }, { - name: "missing db, ds, keystore", + name: "missing ds, keystore", fields: fields{ - DB: nil, - QConfig: cfg.Database(), + DS: nil, }, - wantErrContains: `nil DB -nil DataSource + wantErrContains: `nil DataSource nil Keystore`, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { c := evm.RelayerOpts{ - DB: tt.fields.DB, DS: tt.fields.DS, - QConfig: tt.fields.QConfig, CSAETHKeystore: tt.fields.CSAETHKeystore, } err := c.Validate() diff --git a/core/services/relay/evm/mercury/wsrpc/pb/mercury_wsrpc.pb.go b/core/services/relay/evm/mercury/wsrpc/pb/mercury_wsrpc.pb.go index 0c31a1d7ac9..4d05db4380f 100644 --- a/core/services/relay/evm/mercury/wsrpc/pb/mercury_wsrpc.pb.go +++ b/core/services/relay/evm/mercury/wsrpc/pb/mercury_wsrpc.pb.go @@ -11,7 +11,6 @@ import ( ) // MercuryClient is the client API for Mercury service. -// type MercuryClient interface { Transmit(ctx context.Context, in *TransmitRequest) (*TransmitResponse, error) LatestReport(ctx context.Context, in *LatestReportRequest) (*LatestReportResponse, error) diff --git a/core/services/relay/evm/ocr2keeper.go b/core/services/relay/evm/ocr2keeper.go index 0dd971123c6..78f4b43b43f 100644 --- a/core/services/relay/evm/ocr2keeper.go +++ b/core/services/relay/evm/ocr2keeper.go @@ -27,7 +27,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/transmit" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/upkeepstate" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) @@ -69,17 +68,15 @@ type ocr2keeperRelayer struct { chain legacyevm.Chain lggr logger.Logger ethKeystore keystore.Eth - dbCfg pg.QConfig } // NewOCR2KeeperRelayer is the constructor of ocr2keeperRelayer -func NewOCR2KeeperRelayer(ds sqlutil.DataSource, chain legacyevm.Chain, lggr logger.Logger, ethKeystore keystore.Eth, dbCfg pg.QConfig) OCR2KeeperRelayer { +func NewOCR2KeeperRelayer(ds sqlutil.DataSource, chain legacyevm.Chain, lggr logger.Logger, ethKeystore keystore.Eth) OCR2KeeperRelayer { return &ocr2keeperRelayer{ ds: ds, chain: chain, lggr: lggr, ethKeystore: ethKeystore, - dbCfg: dbCfg, } } diff --git a/core/services/relay/evm/ocr2vrf.go b/core/services/relay/evm/ocr2vrf.go index 07edd1c5ac6..a108151be47 100644 --- a/core/services/relay/evm/ocr2vrf.go +++ b/core/services/relay/evm/ocr2vrf.go @@ -6,8 +6,6 @@ import ( "fmt" "github.com/ethereum/go-ethereum/common" - "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" @@ -44,15 +42,13 @@ var ( // Relayer with added DKG and OCR2VRF provider functions. type ocr2vrfRelayer struct { - db *sqlx.DB chain legacyevm.Chain lggr logger.Logger ethKeystore keystore.Eth } -func NewOCR2VRFRelayer(db *sqlx.DB, chain legacyevm.Chain, lggr logger.Logger, ethKeystore keystore.Eth) OCR2VRFRelayer { +func NewOCR2VRFRelayer(chain legacyevm.Chain, lggr logger.Logger, ethKeystore keystore.Eth) OCR2VRFRelayer { return &ocr2vrfRelayer{ - db: db, chain: chain, lggr: lggr, ethKeystore: ethKeystore, diff --git a/core/services/versioning/orm.go b/core/services/versioning/orm.go index 5a2472eee8e..5f6e3e60222 100644 --- a/core/services/versioning/orm.go +++ b/core/services/versioning/orm.go @@ -23,16 +23,14 @@ type ORM interface { } type orm struct { - ds sqlutil.DataSource - lggr logger.Logger - timeout time.Duration + ds sqlutil.DataSource + lggr logger.Logger } -func NewORM(ds sqlutil.DataSource, lggr logger.Logger, timeout time.Duration) *orm { +func NewORM(ds sqlutil.DataSource, lggr logger.Logger) *orm { return &orm{ - ds: ds, - lggr: lggr.Named("VersioningORM"), - timeout: timeout, + ds: ds, + lggr: lggr.Named("VersioningORM"), } } @@ -47,8 +45,6 @@ func (o *orm) UpsertNodeVersion(ctx context.Context, version NodeVersion) error return errors.Wrapf(err, "%q is not valid semver", version.Version) } - ctx, cancel := context.WithTimeout(ctx, o.timeout) - defer cancel() return sqlutil.TransactDataSource(ctx, o.ds, nil, func(tx sqlutil.DataSource) error { if _, _, err := CheckVersion(ctx, tx, logger.NullLogger, version.Version); err != nil { return err diff --git a/core/services/versioning/orm_test.go b/core/services/versioning/orm_test.go index f655c9c47fe..3504c2bc772 100644 --- a/core/services/versioning/orm_test.go +++ b/core/services/versioning/orm_test.go @@ -10,14 +10,13 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/static" ) func TestORM_NodeVersion_UpsertNodeVersion(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - orm := NewORM(db, logger.TestLogger(t), pg.DefaultQueryTimeout) + orm := NewORM(db, logger.TestLogger(t)) err := orm.UpsertNodeVersion(ctx, NewNodeVersion("9.9.8")) require.NoError(t, err) @@ -66,7 +65,7 @@ func Test_Version_CheckVersion(t *testing.T) { lggr := logger.TestLogger(t) - orm := NewORM(db, lggr, pg.DefaultQueryTimeout) + orm := NewORM(db, lggr) err := orm.UpsertNodeVersion(ctx, NewNodeVersion("9.9.8")) require.NoError(t, err) @@ -101,7 +100,7 @@ func Test_Version_CheckVersion(t *testing.T) { func TestORM_NodeVersion_FindLatestNodeVersion(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - orm := NewORM(db, logger.TestLogger(t), pg.DefaultQueryTimeout) + orm := NewORM(db, logger.TestLogger(t)) // Not Found _, err := orm.FindLatestNodeVersion(ctx) diff --git a/core/services/vrf/delegate_test.go b/core/services/vrf/delegate_test.go index a3962977257..889b19d0e04 100644 --- a/core/services/vrf/delegate_test.go +++ b/core/services/vrf/delegate_test.go @@ -83,10 +83,10 @@ func buildVrfUni(t *testing.T, db *sqlx.DB, cfg chainlink.GeneralConfig) vrfUniv btORM := bridges.NewORM(db) ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr) _, dbConfig, evmConfig := txmgr.MakeTestConfigs(t) - txm, err := txmgr.NewTxm(db, db, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), nil, dbConfig, dbConfig.Listener(), ec, logger.TestLogger(t), nil, ks.Eth(), nil) + txm, err := txmgr.NewTxm(db, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), nil, dbConfig, dbConfig.Listener(), ec, logger.TestLogger(t), nil, ks.Eth(), nil) orm := headtracker.NewORM(*testutils.FixtureChainID, db) require.NoError(t, orm.IdempotentInsertHead(testutils.Context(t), cltest.Head(51))) - jrm := job.NewORM(db, prm, btORM, ks, lggr, cfg.Database()) + jrm := job.NewORM(db, prm, btORM, ks, lggr) t.Cleanup(func() { assert.NoError(t, jrm.Close()) }) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{LogBroadcaster: lb, KeyStore: ks.Eth(), Client: ec, DB: db, GeneralConfig: cfg, TxManager: txm}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) @@ -165,7 +165,8 @@ func setup(t *testing.T) (vrfUniverse, *v1.Listener, job.Job) { vs := testspecs.GenerateVRFSpec(testspecs.VRFSpecParams{PublicKey: vuni.vrfkey.PublicKey.String(), EVMChainID: testutils.FixtureChainID.String()}) jb, err := vrfcommon.ValidatedVRFSpec(vs.Toml()) require.NoError(t, err) - err = vuni.jrm.CreateJob(&jb) + ctx := testutils.Context(t) + err = vuni.jrm.CreateJob(ctx, &jb) require.NoError(t, err) vl, err := vd.ServicesForSpec(testutils.Context(t), jb) require.NoError(t, err) @@ -701,7 +702,8 @@ func Test_VRFV2PlusServiceFailsWhenVRFOwnerProvided(t *testing.T) { toml := "vrfOwnerAddress=\"0xF62fEFb54a0af9D32CDF0Db21C52710844c7eddb\"\n" + vs.Toml() jb, err := vrfcommon.ValidatedVRFSpec(toml) require.NoError(t, err) - err = vuni.jrm.CreateJob(&jb) + ctx := testutils.Context(t) + err = vuni.jrm.CreateJob(ctx, &jb) require.NoError(t, err) _, err = vd.ServicesForSpec(testutils.Context(t), jb) require.Error(t, err) diff --git a/core/services/vrf/v1/integration_test.go b/core/services/vrf/v1/integration_test.go index c28ad9ce3d0..74006639c6e 100644 --- a/core/services/vrf/v1/integration_test.go +++ b/core/services/vrf/v1/integration_test.go @@ -55,10 +55,10 @@ func TestIntegration_VRF_JPV2(t *testing.T) { cu := vrftesthelpers.NewVRFCoordinatorUniverse(t, key1, key2) incomingConfs := 2 app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, config, cu.Backend, key1, key2) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) jb, vrfKey := createVRFJobRegisterKey(t, cu, app, incomingConfs) - require.NoError(t, app.JobSpawner().CreateJob(&jb)) + require.NoError(t, app.JobSpawner().CreateJob(ctx, nil, &jb)) _, err := cu.ConsumerContract.TestRequestRandomness(cu.Carol, vrfKey.PublicKey.MustHash(), big.NewInt(100)) @@ -93,12 +93,12 @@ func TestIntegration_VRF_JPV2(t *testing.T) { // stop jobs as to not cause a race condition in geth simulated backend // between job creating new tx and fulfillment logs polling below - require.NoError(t, app.JobSpawner().DeleteJob(jb.ID)) + require.NoError(t, app.JobSpawner().DeleteJob(ctx, nil, jb.ID)) // Ensure the eth transaction gets confirmed on chain. gomega.NewWithT(t).Eventually(func() bool { - orm := txmgr.NewTxStore(app.GetSqlxDB(), app.GetLogger()) - uc, err2 := orm.CountUnconfirmedTransactions(testutils.Context(t), key1.Address, testutils.SimulatedChainID) + orm := txmgr.NewTxStore(app.GetDB(), app.GetLogger()) + uc, err2 := orm.CountUnconfirmedTransactions(ctx, key1.Address, testutils.SimulatedChainID) require.NoError(t, err2) return uc == 0 }, testutils.WaitTimeout(t), 100*time.Millisecond).Should(gomega.BeTrue()) @@ -116,11 +116,11 @@ func TestIntegration_VRF_JPV2(t *testing.T) { }, testutils.WaitTimeout(t), 500*time.Millisecond).Should(gomega.BeTrue()) // Check that each sending address sent one transaction - n1, err := cu.Backend.PendingNonceAt(testutils.Context(t), key1.Address) + n1, err := cu.Backend.PendingNonceAt(ctx, key1.Address) require.NoError(t, err) require.EqualValues(t, 1, n1) - n2, err := cu.Backend.PendingNonceAt(testutils.Context(t), key2.Address) + n2, err := cu.Backend.PendingNonceAt(ctx, key2.Address) require.NoError(t, err) require.EqualValues(t, 1, n2) }) @@ -142,7 +142,7 @@ func TestIntegration_VRF_WithBHS(t *testing.T) { cu := vrftesthelpers.NewVRFCoordinatorUniverse(t, key) incomingConfs := 2 app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, config, cu.Backend, key) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) // Create VRF Job but do not start it yet jb, vrfKey := createVRFJobRegisterKey(t, cu, app, incomingConfs) @@ -155,7 +155,7 @@ func TestIntegration_VRF_WithBHS(t *testing.T) { // Ensure log poller is ready and has all logs. require.NoError(t, app.GetRelayers().LegacyEVMChains().Slice()[0].LogPoller().Ready()) - require.NoError(t, app.GetRelayers().LegacyEVMChains().Slice()[0].LogPoller().Replay(testutils.Context(t), 1)) + require.NoError(t, app.GetRelayers().LegacyEVMChains().Slice()[0].LogPoller().Replay(ctx, 1)) // Create a VRF request _, err := cu.ConsumerContract.TestRequestRandomness(cu.Carol, @@ -194,7 +194,7 @@ func TestIntegration_VRF_WithBHS(t *testing.T) { } // Start the VRF Job and wait until it's processed - require.NoError(t, app.JobSpawner().CreateJob(&jb)) + require.NoError(t, app.JobSpawner().CreateJob(ctx, nil, &jb)) var runs []pipeline.Run gomega.NewWithT(t).Eventually(func() bool { @@ -209,13 +209,13 @@ func TestIntegration_VRF_WithBHS(t *testing.T) { // stop jobs as to not cause a race condition in geth simulated backend // between job creating new tx and fulfillment logs polling below - require.NoError(t, app.JobSpawner().DeleteJob(jb.ID)) - require.NoError(t, app.JobSpawner().DeleteJob(bhsJob.ID)) + require.NoError(t, app.JobSpawner().DeleteJob(ctx, nil, jb.ID)) + require.NoError(t, app.JobSpawner().DeleteJob(ctx, nil, bhsJob.ID)) // Ensure the eth transaction gets confirmed on chain. gomega.NewWithT(t).Eventually(func() bool { - orm := txmgr.NewTxStore(app.GetSqlxDB(), app.GetLogger()) - uc, err2 := orm.CountUnconfirmedTransactions(testutils.Context(t), key.Address, testutils.SimulatedChainID) + orm := txmgr.NewTxStore(app.GetDB(), app.GetLogger()) + uc, err2 := orm.CountUnconfirmedTransactions(ctx, key.Address, testutils.SimulatedChainID) require.NoError(t, err2) return uc == 0 }, 5*time.Second, 100*time.Millisecond).Should(gomega.BeTrue()) diff --git a/core/services/vrf/v1/listener_v1.go b/core/services/vrf/v1/listener_v1.go index ddf5779deb0..c8029403084 100644 --- a/core/services/vrf/v1/listener_v1.go +++ b/core/services/vrf/v1/listener_v1.go @@ -28,7 +28,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/recovery" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -57,7 +56,6 @@ type Listener struct { Coordinator *solidity_vrf_coordinator_interface.VRFCoordinator PipelineRunner pipeline.Runner Job job.Job - Q pg.Q GethKs vrfcommon.GethKeyStore MailMon *mailbox.Monitor ReqLogs *mailbox.Mailbox[log.Broadcast] @@ -285,6 +283,8 @@ func (lsn *Listener) RunHeadListener(unsubscribe func()) { } func (lsn *Listener) RunLogListener(unsubscribes []func(), minConfs uint32) { + ctx, cancel := lsn.ChStop.NewCtx() + defer cancel() lsn.L.Infow("Listening for run requests", "gasLimit", lsn.FeeCfg.LimitDefault(), "minConfs", minConfs) @@ -304,8 +304,6 @@ func (lsn *Listener) RunLogListener(unsubscribes []func(), minConfs uint32) { break } recovery.WrapRecover(lsn.L, func() { - ctx, cancel := lsn.ChStop.NewCtx() - defer cancel() lsn.handleLog(ctx, lb, minConfs) }) } @@ -488,8 +486,7 @@ func (lsn *Listener) ProcessRequest(ctx context.Context, req request) bool { // The VRF pipeline has no async tasks, so we don't need to check for `incomplete` if _, err = lsn.PipelineRunner.Run(ctx, run, lggr, true, func(tx sqlutil.DataSource) error { // Always mark consumed regardless of whether the proof failed or not. - //TODO restore tx https://smartcontract-it.atlassian.net/browse/BCF-2978 - if err = lsn.Chain.LogBroadcaster().MarkConsumed(ctx, nil, req.lb); err != nil { + if err = lsn.Chain.LogBroadcaster().MarkConsumed(ctx, tx, req.lb); err != nil { lggr.Errorw("Failed mark consumed", "err", err) } return nil diff --git a/core/services/vrf/v2/integration_helpers_test.go b/core/services/vrf/v2/integration_helpers_test.go index 2e0554fca96..d61779c5714 100644 --- a/core/services/vrf/v2/integration_helpers_test.go +++ b/core/services/vrf/v2/integration_helpers_test.go @@ -1207,7 +1207,6 @@ func testSingleConsumerBigGasCallbackSandwich( ownerKey ethkey.KeyV2, uni coordinatorV2UniverseCommon, batchCoordinatorAddress common.Address, - batchEnabled bool, vrfVersion vrfcommon.Version, nativePayment bool, ) { @@ -1324,7 +1323,6 @@ func testSingleConsumerMultipleGasLanes( ownerKey ethkey.KeyV2, uni coordinatorV2UniverseCommon, batchCoordinatorAddress common.Address, - batchEnabled bool, vrfVersion vrfcommon.Version, nativePayment bool, ) { @@ -1694,7 +1692,7 @@ func testMaliciousConsumer( }).Toml() jb, err := vrfcommon.ValidatedVRFSpec(s) require.NoError(t, err) - err = app.JobSpawner().CreateJob(&jb) + err = app.JobSpawner().CreateJob(ctx, nil, &jb) require.NoError(t, err) time.Sleep(1 * time.Second) @@ -1861,7 +1859,7 @@ func testReplayOldRequestsOnStartUp( jb, err := vrfcommon.ValidatedVRFSpec(spec) require.NoError(t, err) t.Log(jb.VRFSpec.PublicKey.MustHash(), vrfKey.PublicKey.MustHash()) - err = app.JobSpawner().CreateJob(&jb) + err = app.JobSpawner().CreateJob(ctx, nil, &jb) require.NoError(t, err) // Wait until all jobs are active and listening for logs diff --git a/core/services/vrf/v2/integration_v2_plus_test.go b/core/services/vrf/v2/integration_v2_plus_test.go index b885473e488..53baaa0eda3 100644 --- a/core/services/vrf/v2/integration_v2_plus_test.go +++ b/core/services/vrf/v2/integration_v2_plus_test.go @@ -646,29 +646,13 @@ func TestVRFV2PlusIntegration_SingleConsumer_NeedsTopUp(t *testing.T) { func TestVRFV2PlusIntegration_SingleConsumer_BigGasCallback_Sandwich(t *testing.T) { ownerKey := cltest.MustGenerateRandomKey(t) uni := newVRFCoordinatorV2PlusUniverse(t, ownerKey, 1, false) - testSingleConsumerBigGasCallbackSandwich( - t, - ownerKey, - uni.coordinatorV2UniverseCommon, - uni.batchCoordinatorContractAddress, - false, - vrfcommon.V2Plus, - false, - ) + testSingleConsumerBigGasCallbackSandwich(t, ownerKey, uni.coordinatorV2UniverseCommon, uni.batchCoordinatorContractAddress, vrfcommon.V2Plus, false) } func TestVRFV2PlusIntegration_SingleConsumer_MultipleGasLanes(t *testing.T) { ownerKey := cltest.MustGenerateRandomKey(t) uni := newVRFCoordinatorV2PlusUniverse(t, ownerKey, 1, false) - testSingleConsumerMultipleGasLanes( - t, - ownerKey, - uni.coordinatorV2UniverseCommon, - uni.batchCoordinatorContractAddress, - false, - vrfcommon.V2Plus, - false, - ) + testSingleConsumerMultipleGasLanes(t, ownerKey, uni.coordinatorV2UniverseCommon, uni.batchCoordinatorContractAddress, vrfcommon.V2Plus, false) } func TestVRFV2PlusIntegration_SingleConsumer_AlwaysRevertingCallback_StillFulfilled(t *testing.T) { @@ -1178,7 +1162,7 @@ func TestVRFV2PlusIntegration_Migration(t *testing.T) { // Fund gas lane. sendEth(t, ownerKey, uni.backend, key1.Address, 10) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) // Create VRF job using key1 and key2 on the same gas lane. jbs := createVRFJobs( @@ -1234,7 +1218,7 @@ func TestVRFV2PlusIntegration_Migration(t *testing.T) { require.NoError(t, err) linkContractBalance, err := uni.linkContract.BalanceOf(nil, uni.migrationTestCoordinatorAddress) require.NoError(t, err) - balance, err := uni.backend.BalanceAt(testutils.Context(t), uni.migrationTestCoordinatorAddress, nil) + balance, err := uni.backend.BalanceAt(ctx, uni.migrationTestCoordinatorAddress, nil) require.NoError(t, err) require.Equal(t, subV1.Balance(), totalLinkBalance) diff --git a/core/services/vrf/v2/integration_v2_reverted_txns_test.go b/core/services/vrf/v2/integration_v2_reverted_txns_test.go index dfee450b6a2..25e3afcf751 100644 --- a/core/services/vrf/v2/integration_v2_reverted_txns_test.go +++ b/core/services/vrf/v2/integration_v2_reverted_txns_test.go @@ -448,7 +448,7 @@ func createVRFJobsNew( jb, err := vrfcommon.ValidatedVRFSpec(s) t.Log(jb.VRFSpec.PublicKey.MustHash(), vrfkey.PublicKey.MustHash()) require.NoError(t, err) - err = app.JobSpawner().CreateJob(&jb) + err = app.JobSpawner().CreateJob(ctx, nil, &jb) require.NoError(t, err) registerProvingKeyHelper(t, uni.coordinatorV2UniverseCommon, coordinator, vrfkey, ptr(gasLanePrices[i].ToInt().Uint64())) jobs = append(jobs, jb) diff --git a/core/services/vrf/v2/integration_v2_test.go b/core/services/vrf/v2/integration_v2_test.go index 543ec943527..e8d4fd255f7 100644 --- a/core/services/vrf/v2/integration_v2_test.go +++ b/core/services/vrf/v2/integration_v2_test.go @@ -574,7 +574,7 @@ func createVRFJobs( jb, err := vrfcommon.ValidatedVRFSpec(spec) require.NoError(t, err) t.Log(jb.VRFSpec.PublicKey.MustHash(), vrfkey.PublicKey.MustHash()) - err = app.JobSpawner().CreateJob(&jb) + err = app.JobSpawner().CreateJob(ctx, nil, &jb) require.NoError(t, err) registerProvingKeyHelper(t, uni, coordinator, vrfkey, ptr(gasLanePrices[i].ToInt().Uint64())) jobs = append(jobs, jb) @@ -1427,29 +1427,13 @@ func TestVRFV2Integration_SingleConsumer_NeedsTopUp(t *testing.T) { func TestVRFV2Integration_SingleConsumer_BigGasCallback_Sandwich(t *testing.T) { ownerKey := cltest.MustGenerateRandomKey(t) uni := newVRFCoordinatorV2Universe(t, ownerKey, 1) - testSingleConsumerBigGasCallbackSandwich( - t, - ownerKey, - uni.coordinatorV2UniverseCommon, - uni.batchCoordinatorContractAddress, - false, - vrfcommon.V2, - false, - ) + testSingleConsumerBigGasCallbackSandwich(t, ownerKey, uni.coordinatorV2UniverseCommon, uni.batchCoordinatorContractAddress, vrfcommon.V2, false) } func TestVRFV2Integration_SingleConsumer_MultipleGasLanes(t *testing.T) { ownerKey := cltest.MustGenerateRandomKey(t) uni := newVRFCoordinatorV2Universe(t, ownerKey, 1) - testSingleConsumerMultipleGasLanes( - t, - ownerKey, - uni.coordinatorV2UniverseCommon, - uni.batchCoordinatorContractAddress, - false, - vrfcommon.V2, - false, - ) + testSingleConsumerMultipleGasLanes(t, ownerKey, uni.coordinatorV2UniverseCommon, uni.batchCoordinatorContractAddress, vrfcommon.V2, false) } func TestVRFV2Integration_SingleConsumer_AlwaysRevertingCallback_StillFulfilled(t *testing.T) { diff --git a/core/services/vrf/vrftesthelpers/helpers.go b/core/services/vrf/vrftesthelpers/helpers.go index 77d3f33a653..33ad8470731 100644 --- a/core/services/vrf/vrftesthelpers/helpers.go +++ b/core/services/vrf/vrftesthelpers/helpers.go @@ -74,7 +74,8 @@ func CreateAndStartBHSJob( jb, err := blockhashstore.ValidatedSpec(s.Toml()) require.NoError(t, err) - require.NoError(t, app.JobSpawner().CreateJob(&jb)) + ctx := testutils.Context(t) + require.NoError(t, app.JobSpawner().CreateJob(ctx, nil, &jb)) gomega.NewWithT(t).Eventually(func() bool { jbs := app.JobSpawner().ActiveJobs() for _, jb := range jbs { @@ -115,7 +116,8 @@ func CreateAndStartBlockHeaderFeederJob( jb, err := blockheaderfeeder.ValidatedSpec(s.Toml()) require.NoError(t, err) - require.NoError(t, app.JobSpawner().CreateJob(&jb)) + ctx := testutils.Context(t) + require.NoError(t, app.JobSpawner().CreateJob(ctx, nil, &jb)) gomega.NewWithT(t).Eventually(func() bool { jbs := app.JobSpawner().ActiveJobs() for _, jb := range jbs { diff --git a/core/services/webhook/authorizer.go b/core/services/webhook/authorizer.go index c745c5d0b09..f5409cfbacc 100644 --- a/core/services/webhook/authorizer.go +++ b/core/services/webhook/authorizer.go @@ -24,29 +24,29 @@ var ( _ Authorizer = &neverAuthorizer{} ) -func NewAuthorizer(db sqlutil.DataSource, user *sessions.User, ei *bridges.ExternalInitiator) Authorizer { +func NewAuthorizer(ds sqlutil.DataSource, user *sessions.User, ei *bridges.ExternalInitiator) Authorizer { if user != nil { return &alwaysAuthorizer{} } else if ei != nil { - return NewEIAuthorizer(db, *ei) + return NewEIAuthorizer(ds, *ei) } return &neverAuthorizer{} } type eiAuthorizer struct { - db sqlutil.DataSource + ds sqlutil.DataSource ei bridges.ExternalInitiator } -func NewEIAuthorizer(db sqlutil.DataSource, ei bridges.ExternalInitiator) *eiAuthorizer { - return &eiAuthorizer{db, ei} +func NewEIAuthorizer(ds sqlutil.DataSource, ei bridges.ExternalInitiator) *eiAuthorizer { + return &eiAuthorizer{ds, ei} } func (ea *eiAuthorizer) CanRun(ctx context.Context, config AuthorizerConfig, jobUUID uuid.UUID) (can bool, err error) { if !config.ExternalInitiatorsEnabled() { return false, nil } - row := ea.db.QueryRowxContext(ctx, ` + row := ea.ds.QueryRowxContext(ctx, ` SELECT EXISTS ( SELECT 1 FROM external_initiator_webhook_specs JOIN jobs ON external_initiator_webhook_specs.webhook_spec_id = jobs.webhook_spec_id diff --git a/core/services/webhook/authorizer_test.go b/core/services/webhook/authorizer_test.go index 82af7c6fcce..202791c26c2 100644 --- a/core/services/webhook/authorizer_test.go +++ b/core/services/webhook/authorizer_test.go @@ -8,9 +8,8 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/bridges" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" "github.com/smartcontractkit/chainlink/v2/core/sessions" diff --git a/core/services/webhook/external_initiator_manager.go b/core/services/webhook/external_initiator_manager.go index 0c035abde7a..2f9a176906d 100644 --- a/core/services/webhook/external_initiator_manager.go +++ b/core/services/webhook/external_initiator_manager.go @@ -11,12 +11,9 @@ import ( "github.com/lib/pq" "github.com/pkg/errors" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/bridges" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/static" "github.com/smartcontractkit/chainlink/v2/core/store/models" ) @@ -27,7 +24,7 @@ import ( type ExternalInitiatorManager interface { Notify(ctx context.Context, webhookSpecID int32) error DeleteJob(ctx context.Context, webhookSpecID int32) error - FindExternalInitiatorByName(name string) (bridges.ExternalInitiator, error) + FindExternalInitiatorByName(ctx context.Context, name string) (bridges.ExternalInitiator, error) } //go:generate mockery --quiet --name HTTPClient --output ./mocks/ --case=underscore @@ -36,25 +33,24 @@ type HTTPClient interface { } type externalInitiatorManager struct { - q pg.Q + ds sqlutil.DataSource httpclient HTTPClient } var _ ExternalInitiatorManager = (*externalInitiatorManager)(nil) // NewExternalInitiatorManager returns the concrete externalInitiatorManager -func NewExternalInitiatorManager(db *sqlx.DB, httpclient HTTPClient, lggr logger.Logger, cfg pg.QConfig) *externalInitiatorManager { - namedLogger := lggr.Named("ExternalInitiatorManager") +func NewExternalInitiatorManager(ds sqlutil.DataSource, httpclient HTTPClient) *externalInitiatorManager { return &externalInitiatorManager{ - q: pg.NewQ(db, namedLogger, cfg), + ds: ds, httpclient: httpclient, } } // Notify sends a POST notification to the External Initiator // responsible for initiating the Job Spec. -func (m externalInitiatorManager) Notify(ctx context.Context, webhookSpecID int32) error { - eiWebhookSpecs, jobID, err := m.Load(webhookSpecID) +func (m *externalInitiatorManager) Notify(ctx context.Context, webhookSpecID int32) error { + eiWebhookSpecs, jobID, err := m.Load(ctx, webhookSpecID) if err != nil { return err } @@ -90,19 +86,21 @@ func (m externalInitiatorManager) Notify(ctx context.Context, webhookSpecID int3 return nil } -func (m externalInitiatorManager) Load(webhookSpecID int32) (eiWebhookSpecs []job.ExternalInitiatorWebhookSpec, jobID uuid.UUID, err error) { - err = m.q.Transaction(func(tx pg.Queryer) error { - if err = tx.Get(&jobID, "SELECT external_job_id FROM jobs WHERE webhook_spec_id = $1", webhookSpecID); err != nil { +func (m *externalInitiatorManager) Load(ctx context.Context, webhookSpecID int32) (eiWebhookSpecs []job.ExternalInitiatorWebhookSpec, jobID uuid.UUID, err error) { + err = sqlutil.Transact(ctx, func(ds sqlutil.DataSource) *externalInitiatorManager { + return NewExternalInitiatorManager(ds, m.httpclient) + }, m.ds, nil, func(tx *externalInitiatorManager) error { + if err = tx.ds.GetContext(ctx, &jobID, "SELECT external_job_id FROM jobs WHERE webhook_spec_id = $1", webhookSpecID); err != nil { if err = errors.Wrapf(err, "failed to load job ID from job for webhook spec with ID %d", webhookSpecID); err != nil { return err } } - if err = tx.Select(&eiWebhookSpecs, "SELECT * FROM external_initiator_webhook_specs WHERE external_initiator_webhook_specs.webhook_spec_id = $1", webhookSpecID); err != nil { + if err = tx.ds.SelectContext(ctx, &eiWebhookSpecs, "SELECT * FROM external_initiator_webhook_specs WHERE external_initiator_webhook_specs.webhook_spec_id = $1", webhookSpecID); err != nil { if err = errors.Wrapf(err, "failed to load external_initiator_webhook_specs for webhook_spec_id %d", webhookSpecID); err != nil { return err } } - if err = m.eagerLoadExternalInitiator(tx, eiWebhookSpecs); err != nil { + if err = tx.eagerLoadExternalInitiator(ctx, eiWebhookSpecs); err != nil { if err = errors.Wrapf(err, "failed to preload ExternalInitiator for webhook_spec_id %d", webhookSpecID); err != nil { return err } @@ -113,7 +111,7 @@ func (m externalInitiatorManager) Load(webhookSpecID int32) (eiWebhookSpecs []jo return } -func (m externalInitiatorManager) eagerLoadExternalInitiator(q pg.Queryer, txs []job.ExternalInitiatorWebhookSpec) error { +func (m *externalInitiatorManager) eagerLoadExternalInitiator(ctx context.Context, txs []job.ExternalInitiatorWebhookSpec) error { var ids []int64 for _, tx := range txs { ids = append(ids, tx.ExternalInitiatorID) @@ -122,7 +120,7 @@ func (m externalInitiatorManager) eagerLoadExternalInitiator(q pg.Queryer, txs [ return nil } var externalInitiators []bridges.ExternalInitiator - if err := sqlx.Select(q, &externalInitiators, `SELECT * FROM external_initiators WHERE external_initiators.id = ANY($1);`, pq.Array(ids)); err != nil { + if err := m.ds.SelectContext(ctx, &externalInitiators, `SELECT * FROM external_initiators WHERE external_initiators.id = ANY($1);`, pq.Array(ids)); err != nil { return err } @@ -137,8 +135,8 @@ func (m externalInitiatorManager) eagerLoadExternalInitiator(q pg.Queryer, txs [ return nil } -func (m externalInitiatorManager) DeleteJob(ctx context.Context, webhookSpecID int32) error { - eiWebhookSpecs, jobID, err := m.Load(webhookSpecID) +func (m *externalInitiatorManager) DeleteJob(ctx context.Context, webhookSpecID int32) error { + eiWebhookSpecs, jobID, err := m.Load(ctx, webhookSpecID) if err != nil { return err } @@ -166,9 +164,9 @@ func (m externalInitiatorManager) DeleteJob(ctx context.Context, webhookSpecID i return nil } -func (m externalInitiatorManager) FindExternalInitiatorByName(name string) (bridges.ExternalInitiator, error) { +func (m *externalInitiatorManager) FindExternalInitiatorByName(ctx context.Context, name string) (bridges.ExternalInitiator, error) { var exi bridges.ExternalInitiator - err := m.q.Get(&exi, "SELECT * FROM external_initiators WHERE lower(external_initiators.name) = lower($1)", name) + err := m.ds.GetContext(ctx, &exi, "SELECT * FROM external_initiators WHERE lower(external_initiators.name) = lower($1)", name) return exi, err } @@ -211,6 +209,6 @@ var _ ExternalInitiatorManager = (*NullExternalInitiatorManager)(nil) func (NullExternalInitiatorManager) Notify(context.Context, int32) error { return nil } func (NullExternalInitiatorManager) DeleteJob(context.Context, int32) error { return nil } -func (NullExternalInitiatorManager) FindExternalInitiatorByName(name string) (bridges.ExternalInitiator, error) { +func (NullExternalInitiatorManager) FindExternalInitiatorByName(ctx context.Context, name string) (bridges.ExternalInitiator, error) { return bridges.ExternalInitiator{}, nil } diff --git a/core/services/webhook/external_initiator_manager_test.go b/core/services/webhook/external_initiator_manager_test.go index 22ab50513cf..a2402b4114d 100644 --- a/core/services/webhook/external_initiator_manager_test.go +++ b/core/services/webhook/external_initiator_manager_test.go @@ -17,15 +17,14 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" _ "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" webhookmocks "github.com/smartcontractkit/chainlink/v2/core/services/webhook/mocks" ) func Test_ExternalInitiatorManager_Load(t *testing.T) { + ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := pgtest.NewQConfig(true) borm := bridges.NewORM(db) eiFoo := cltest.MustInsertExternalInitiator(t, borm) @@ -39,21 +38,21 @@ func Test_ExternalInitiatorManager_Load(t *testing.T) { pgtest.MustExec(t, db, `INSERT INTO external_initiator_webhook_specs (external_initiator_id, webhook_spec_id, spec) VALUES ($1,$2,$3)`, eiBar.ID, webhookSpecTwoEIs.ID, `{"ei": "bar", "name": "webhookSpecTwoEIs"}`) pgtest.MustExec(t, db, `INSERT INTO external_initiator_webhook_specs (external_initiator_id, webhook_spec_id, spec) VALUES ($1,$2,$3)`, eiFoo.ID, webhookSpecOneEI.ID, `{"ei": "foo", "name": "webhookSpecOneEI"}`) - eim := webhook.NewExternalInitiatorManager(db, nil, logger.TestLogger(t), cfg) + eim := webhook.NewExternalInitiatorManager(db, nil) - eiWebhookSpecs, jobID, err := eim.Load(webhookSpecNoEIs.ID) + eiWebhookSpecs, jobID, err := eim.Load(ctx, webhookSpecNoEIs.ID) require.NoError(t, err) assert.Len(t, eiWebhookSpecs, 0) assert.Equal(t, jb3.ExternalJobID, jobID) - eiWebhookSpecs, jobID, err = eim.Load(webhookSpecOneEI.ID) + eiWebhookSpecs, jobID, err = eim.Load(ctx, webhookSpecOneEI.ID) require.NoError(t, err) assert.Len(t, eiWebhookSpecs, 1) assert.Equal(t, `{"ei": "foo", "name": "webhookSpecOneEI"}`, eiWebhookSpecs[0].Spec.Raw) assert.Equal(t, eiFoo.ID, eiWebhookSpecs[0].ExternalInitiator.ID) assert.Equal(t, jb1.ExternalJobID, jobID) - eiWebhookSpecs, jobID, err = eim.Load(webhookSpecTwoEIs.ID) + eiWebhookSpecs, jobID, err = eim.Load(ctx, webhookSpecTwoEIs.ID) require.NoError(t, err) assert.Len(t, eiWebhookSpecs, 2) assert.Equal(t, jb2.ExternalJobID, jobID) @@ -62,7 +61,6 @@ func Test_ExternalInitiatorManager_Load(t *testing.T) { func Test_ExternalInitiatorManager_Notify(t *testing.T) { ctx := tests.Context(t) db := pgtest.NewSqlxDB(t) - cfg := pgtest.NewQConfig(true) borm := bridges.NewORM(db) eiWithURL := cltest.MustInsertExternalInitiatorWithOpts(t, borm, cltest.ExternalInitiatorOpts{ @@ -79,7 +77,7 @@ func Test_ExternalInitiatorManager_Notify(t *testing.T) { pgtest.MustExec(t, db, `INSERT INTO external_initiator_webhook_specs (external_initiator_id, webhook_spec_id, spec) VALUES ($1,$2,$3)`, eiNoURL.ID, webhookSpecTwoEIs.ID, `{"ei": "bar", "name": "webhookSpecTwoEIs"}`) client := webhookmocks.NewHTTPClient(t) - eim := webhook.NewExternalInitiatorManager(db, client, logger.TestLogger(t), cfg) + eim := webhook.NewExternalInitiatorManager(db, client) // Does nothing with no EI require.NoError(t, eim.Notify(ctx, webhookSpecNoEIs.ID)) @@ -102,7 +100,6 @@ func Test_ExternalInitiatorManager_Notify(t *testing.T) { func Test_ExternalInitiatorManager_DeleteJob(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := pgtest.NewQConfig(true) borm := bridges.NewORM(db) eiWithURL := cltest.MustInsertExternalInitiatorWithOpts(t, borm, cltest.ExternalInitiatorOpts{ @@ -119,7 +116,7 @@ func Test_ExternalInitiatorManager_DeleteJob(t *testing.T) { pgtest.MustExec(t, db, `INSERT INTO external_initiator_webhook_specs (external_initiator_id, webhook_spec_id, spec) VALUES ($1,$2,$3)`, eiNoURL.ID, webhookSpecTwoEIs.ID, `{"ei": "bar", "name": "webhookSpecTwoEIs"}`) client := webhookmocks.NewHTTPClient(t) - eim := webhook.NewExternalInitiatorManager(db, client, logger.TestLogger(t), cfg) + eim := webhook.NewExternalInitiatorManager(db, client) // Does nothing with no EI require.NoError(t, eim.DeleteJob(ctx, webhookSpecNoEIs.ID)) diff --git a/core/services/webhook/mocks/external_initiator_manager.go b/core/services/webhook/mocks/external_initiator_manager.go index 9711ae686ea..7a3ee29f62f 100644 --- a/core/services/webhook/mocks/external_initiator_manager.go +++ b/core/services/webhook/mocks/external_initiator_manager.go @@ -33,9 +33,9 @@ func (_m *ExternalInitiatorManager) DeleteJob(ctx context.Context, webhookSpecID return r0 } -// FindExternalInitiatorByName provides a mock function with given fields: name -func (_m *ExternalInitiatorManager) FindExternalInitiatorByName(name string) (bridges.ExternalInitiator, error) { - ret := _m.Called(name) +// FindExternalInitiatorByName provides a mock function with given fields: ctx, name +func (_m *ExternalInitiatorManager) FindExternalInitiatorByName(ctx context.Context, name string) (bridges.ExternalInitiator, error) { + ret := _m.Called(ctx, name) if len(ret) == 0 { panic("no return value specified for FindExternalInitiatorByName") @@ -43,17 +43,17 @@ func (_m *ExternalInitiatorManager) FindExternalInitiatorByName(name string) (br var r0 bridges.ExternalInitiator var r1 error - if rf, ok := ret.Get(0).(func(string) (bridges.ExternalInitiator, error)); ok { - return rf(name) + if rf, ok := ret.Get(0).(func(context.Context, string) (bridges.ExternalInitiator, error)); ok { + return rf(ctx, name) } - if rf, ok := ret.Get(0).(func(string) bridges.ExternalInitiator); ok { - r0 = rf(name) + if rf, ok := ret.Get(0).(func(context.Context, string) bridges.ExternalInitiator); ok { + r0 = rf(ctx, name) } else { r0 = ret.Get(0).(bridges.ExternalInitiator) } - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, name) } else { r1 = ret.Error(1) } diff --git a/core/services/webhook/validate.go b/core/services/webhook/validate.go index 6066a863ff7..a6d6aa72e83 100644 --- a/core/services/webhook/validate.go +++ b/core/services/webhook/validate.go @@ -1,6 +1,8 @@ package webhook import ( + "context" + "github.com/pelletier/go-toml" "github.com/pkg/errors" "go.uber.org/multierr" @@ -18,7 +20,7 @@ type TOMLWebhookSpec struct { ExternalInitiators []TOMLWebhookSpecExternalInitiator `toml:"externalInitiators"` } -func ValidatedWebhookSpec(tomlString string, externalInitiatorManager ExternalInitiatorManager) (jb job.Job, err error) { +func ValidatedWebhookSpec(ctx context.Context, tomlString string, externalInitiatorManager ExternalInitiatorManager) (jb job.Job, err error) { var tree *toml.Tree tree, err = toml.Load(tomlString) if err != nil { @@ -40,7 +42,7 @@ func ValidatedWebhookSpec(tomlString string, externalInitiatorManager ExternalIn var externalInitiatorWebhookSpecs []job.ExternalInitiatorWebhookSpec for _, eiSpec := range tomlSpec.ExternalInitiators { - ei, findErr := externalInitiatorManager.FindExternalInitiatorByName(eiSpec.Name) + ei, findErr := externalInitiatorManager.FindExternalInitiatorByName(ctx, eiSpec.Name) if findErr != nil { err = multierr.Combine(err, errors.Wrapf(findErr, "unable to find external initiator named %s", eiSpec.Name)) continue diff --git a/core/services/webhook/validate_test.go b/core/services/webhook/validate_test.go index f6993f6aefe..8d398fc0b68 100644 --- a/core/services/webhook/validate_test.go +++ b/core/services/webhook/validate_test.go @@ -6,9 +6,11 @@ import ( "github.com/manyminds/api2go/jsonapi" "github.com/pkg/errors" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/bridges" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" webhookmocks "github.com/smartcontractkit/chainlink/v2/core/services/webhook/mocks" @@ -96,8 +98,8 @@ func TestValidatedWebJobSpec(t *testing.T) { """ `, mock: func(t *testing.T, eim *webhookmocks.ExternalInitiatorManager) { - eim.On("FindExternalInitiatorByName", "foo").Return(bridges.ExternalInitiator{ID: 42}, nil).Once() - eim.On("FindExternalInitiatorByName", "bar").Return(bridges.ExternalInitiator{ID: 43}, nil).Once() + eim.On("FindExternalInitiatorByName", mock.Anything, "foo").Return(bridges.ExternalInitiator{ID: 42}, nil).Once() + eim.On("FindExternalInitiatorByName", mock.Anything, "bar").Return(bridges.ExternalInitiator{ID: 43}, nil).Once() }, assertion: func(t *testing.T, s job.Job, err error) { require.NoError(t, err) @@ -134,9 +136,9 @@ func TestValidatedWebJobSpec(t *testing.T) { """ `, mock: func(t *testing.T, eim *webhookmocks.ExternalInitiatorManager) { - eim.On("FindExternalInitiatorByName", "foo").Return(bridges.ExternalInitiator{ID: 42}, nil).Once() - eim.On("FindExternalInitiatorByName", "bar").Return(bridges.ExternalInitiator{}, errors.New("something exploded")).Once() - eim.On("FindExternalInitiatorByName", "baz").Return(bridges.ExternalInitiator{}, errors.New("something exploded")).Once() + eim.On("FindExternalInitiatorByName", mock.Anything, "foo").Return(bridges.ExternalInitiator{ID: 42}, nil).Once() + eim.On("FindExternalInitiatorByName", mock.Anything, "bar").Return(bridges.ExternalInitiator{}, errors.New("something exploded")).Once() + eim.On("FindExternalInitiatorByName", mock.Anything, "baz").Return(bridges.ExternalInitiator{}, errors.New("something exploded")).Once() }, assertion: func(t *testing.T, s job.Job, err error) { require.EqualError(t, err, "unable to find external initiator named bar: something exploded; unable to find external initiator named baz: something exploded") @@ -147,11 +149,12 @@ func TestValidatedWebJobSpec(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) eim := new(webhookmocks.ExternalInitiatorManager) if tc.mock != nil { tc.mock(t, eim) } - s, err := webhook.ValidatedWebhookSpec(tc.toml, eim) + s, err := webhook.ValidatedWebhookSpec(ctx, tc.toml, eim) tc.assertion(t, s, err) }) } diff --git a/core/sessions/ldapauth/sync.go b/core/sessions/ldapauth/sync.go index 74c606a9684..a6e0366e21d 100644 --- a/core/sessions/ldapauth/sync.go +++ b/core/sessions/ldapauth/sync.go @@ -1,23 +1,23 @@ package ldapauth import ( + "context" "errors" "fmt" "time" "github.com/go-ldap/ldap/v3" - "github.com/jmoiron/sqlx" "github.com/lib/pq" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/sessions" ) type LDAPServerStateSyncer struct { - q pg.Q + ds sqlutil.DataSource ldapClient LDAPClient config config.LDAP lggr logger.Logger @@ -26,14 +26,13 @@ type LDAPServerStateSyncer struct { // NewLDAPServerStateSync creates a reaper that cleans stale sessions from the store. func NewLDAPServerStateSync( - db *sqlx.DB, - pgCfg pg.QConfig, + ds sqlutil.DataSource, config config.LDAP, lggr logger.Logger, ) *utils.SleeperTask { namedLogger := lggr.Named("LDAPServerStateSync") serverSync := LDAPServerStateSyncer{ - q: pg.NewQ(db, namedLogger, pgCfg), + ds: ds, ldapClient: newLDAPClient(config), config: config, lggr: namedLogger, @@ -65,14 +64,15 @@ func (ldSync *LDAPServerStateSyncer) StartWorkOnTimer() { } func (ldSync *LDAPServerStateSyncer) Work() { + ctx := context.Background() // TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 // Purge expired ldap_sessions and ldap_user_api_tokens recordCreationStaleThreshold := ldSync.config.SessionTimeout().Before(time.Now()) - err := ldSync.deleteStaleSessions(recordCreationStaleThreshold) + err := ldSync.deleteStaleSessions(ctx, recordCreationStaleThreshold) if err != nil { ldSync.lggr.Error("unable to expire local LDAP sessions: ", err) } recordCreationStaleThreshold = ldSync.config.UserAPITokenDuration().Before(time.Now()) - err = ldSync.deleteStaleAPITokens(recordCreationStaleThreshold) + err = ldSync.deleteStaleAPITokens(ctx, recordCreationStaleThreshold) if err != nil { ldSync.lggr.Error("unable to expire user API tokens: ", err) } @@ -160,18 +160,18 @@ func (ldSync *LDAPServerStateSyncer) Work() { // upstreamUserStateMap is now the most up to date source of truth // Now sync database sessions and roles with new data - err = ldSync.q.Transaction(func(tx pg.Queryer) error { + err = sqlutil.TransactDataSource(ctx, ldSync.ds, nil, func(tx sqlutil.DataSource) error { // First, purge users present in the local ldap_sessions table but not in the upstream server type LDAPSession struct { UserEmail string UserRole sessions.UserRole } var existingSessions []LDAPSession - if err = tx.Select(&existingSessions, "SELECT user_email, user_role FROM ldap_sessions WHERE localauth_user = false"); err != nil { + if err = tx.SelectContext(ctx, &existingSessions, "SELECT user_email, user_role FROM ldap_sessions WHERE localauth_user = false"); err != nil { return fmt.Errorf("unable to query ldap_sessions table: %w", err) } var existingAPITokens []LDAPSession - if err = tx.Select(&existingAPITokens, "SELECT user_email, user_role FROM ldap_user_api_tokens WHERE localauth_user = false"); err != nil { + if err = tx.SelectContext(ctx, &existingAPITokens, "SELECT user_email, user_role FROM ldap_user_api_tokens WHERE localauth_user = false"); err != nil { return fmt.Errorf("unable to query ldap_user_api_tokens table: %w", err) } @@ -202,7 +202,7 @@ func (ldSync *LDAPServerStateSyncer) Work() { // Remove any active sessions this user may have if len(emailsToPurge) > 0 { - _, err = ldSync.q.Exec("DELETE FROM ldap_sessions WHERE user_email = ANY($1)", pq.Array(emailsToPurge)) + _, err = tx.ExecContext(ctx, "DELETE FROM ldap_sessions WHERE user_email = ANY($1)", pq.Array(emailsToPurge)) if err != nil { return err } @@ -210,7 +210,7 @@ func (ldSync *LDAPServerStateSyncer) Work() { // Remove any active API tokens this user may have if len(apiTokenEmailsToPurge) > 0 { - _, err = ldSync.q.Exec("DELETE FROM ldap_user_api_tokens WHERE user_email = ANY($1)", pq.Array(apiTokenEmailsToPurge)) + _, err = tx.ExecContext(ctx, "DELETE FROM ldap_user_api_tokens WHERE user_email = ANY($1)", pq.Array(apiTokenEmailsToPurge)) if err != nil { return err } @@ -235,14 +235,14 @@ func (ldSync *LDAPServerStateSyncer) Work() { if len(emailValues) != 0 { // Set new role state for all rows in single Exec query := fmt.Sprintf("UPDATE ldap_sessions SET user_role = CASE %s ELSE user_role END", queryWhenClause) - _, err = ldSync.q.Exec(query, emailValues...) + _, err = tx.ExecContext(ctx, query, emailValues...) if err != nil { return err } // Update role of API tokens as well query = fmt.Sprintf("UPDATE ldap_user_api_tokens SET user_role = CASE %s ELSE user_role END", queryWhenClause) - _, err = ldSync.q.Exec(query, emailValues...) + _, err = tx.ExecContext(ctx, query, emailValues...) if err != nil { return err } @@ -258,14 +258,14 @@ func (ldSync *LDAPServerStateSyncer) Work() { } // deleteStaleSessions deletes all ldap_sessions before the passed time. -func (ldSync *LDAPServerStateSyncer) deleteStaleSessions(before time.Time) error { - _, err := ldSync.q.Exec("DELETE FROM ldap_sessions WHERE created_at < $1", before) +func (ldSync *LDAPServerStateSyncer) deleteStaleSessions(ctx context.Context, before time.Time) error { + _, err := ldSync.ds.ExecContext(ctx, "DELETE FROM ldap_sessions WHERE created_at < $1", before) return err } // deleteStaleAPITokens deletes all ldap_user_api_tokens before the passed time. -func (ldSync *LDAPServerStateSyncer) deleteStaleAPITokens(before time.Time) error { - _, err := ldSync.q.Exec("DELETE FROM ldap_user_api_tokens WHERE created_at < $1", before) +func (ldSync *LDAPServerStateSyncer) deleteStaleAPITokens(ctx context.Context, before time.Time) error { + _, err := ldSync.ds.ExecContext(ctx, "DELETE FROM ldap_user_api_tokens WHERE created_at < $1", before) return err } diff --git a/core/sessions/localauth/reaper.go b/core/sessions/localauth/reaper.go index eef884367aa..7b91e4ce2c0 100644 --- a/core/sessions/localauth/reaper.go +++ b/core/sessions/localauth/reaper.go @@ -1,16 +1,17 @@ package localauth import ( - "database/sql" + "context" "time" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/logger" ) type sessionReaper struct { - db *sql.DB + ds sqlutil.DataSource config SessionReaperConfig lggr logger.Logger } @@ -21,9 +22,9 @@ type SessionReaperConfig interface { } // NewSessionReaper creates a reaper that cleans stale sessions from the store. -func NewSessionReaper(db *sql.DB, config SessionReaperConfig, lggr logger.Logger) *utils.SleeperTask { +func NewSessionReaper(ds sqlutil.DataSource, config SessionReaperConfig, lggr logger.Logger) *utils.SleeperTask { return utils.NewSleeperTask(&sessionReaper{ - db, + ds, config, lggr.Named("SessionReaper"), }) @@ -34,16 +35,17 @@ func (sr *sessionReaper) Name() string { } func (sr *sessionReaper) Work() { + ctx := context.Background() //TODO https://smartcontract-it.atlassian.net/browse/BCF-2887 recordCreationStaleThreshold := sr.config.SessionReaperExpiration().Before( sr.config.SessionTimeout().Before(time.Now())) - err := sr.deleteStaleSessions(recordCreationStaleThreshold) + err := sr.deleteStaleSessions(ctx, recordCreationStaleThreshold) if err != nil { sr.lggr.Error("unable to reap stale sessions: ", err) } } // DeleteStaleSessions deletes all sessions before the passed time. -func (sr *sessionReaper) deleteStaleSessions(before time.Time) error { - _, err := sr.db.Exec("DELETE FROM sessions WHERE last_used < $1", before) +func (sr *sessionReaper) deleteStaleSessions(ctx context.Context, before time.Time) error { + _, err := sr.ds.ExecContext(ctx, "DELETE FROM sessions WHERE last_used < $1", before) return err } diff --git a/core/sessions/localauth/reaper_test.go b/core/sessions/localauth/reaper_test.go index 47413c5fc62..806c9448682 100644 --- a/core/sessions/localauth/reaper_test.go +++ b/core/sessions/localauth/reaper_test.go @@ -37,7 +37,7 @@ func TestSessionReaper_ReapSessions(t *testing.T) { lggr := logger.TestLogger(t) orm := localauth.NewORM(db, config.SessionTimeout().Duration(), lggr, audit.NoopLogger) - r := localauth.NewSessionReaper(db.DB, config, lggr) + r := localauth.NewSessionReaper(db, config, lggr) t.Cleanup(func() { assert.NoError(t, r.Stop()) }) diff --git a/core/store/migrate/migrate.go b/core/store/migrate/migrate.go index aff3229e92a..c8f70e87383 100644 --- a/core/store/migrate/migrate.go +++ b/core/store/migrate/migrate.go @@ -9,13 +9,12 @@ import ( "strconv" "strings" - "github.com/jmoiron/sqlx" pkgerrors "github.com/pkg/errors" "github.com/pressly/goose/v3" "gopkg.in/guregu/null.v4" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/config/env" - "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/store/migrate/migrations" // Invoke init() functions within migrations pkg. @@ -36,7 +35,7 @@ func init() { } // Ensure we migrated from v1 migrations to goose_migrations -func ensureMigrated(ctx context.Context, db *sql.DB, lggr logger.Logger) error { +func ensureMigrated(ctx context.Context, db *sql.DB) error { sqlxDB := pg.WrapDbWithSqlx(db) var names []string err := sqlxDB.SelectContext(ctx, &names, `SELECT id FROM migrations`) @@ -44,12 +43,10 @@ func ensureMigrated(ctx context.Context, db *sql.DB, lggr logger.Logger) error { // already migrated return nil } - err = pg.SqlTransaction(ctx, db, lggr, func(tx *sqlx.Tx) error { - // ensure that no legacy job specs are present: we _must_ bail out early if - // so because otherwise we run the risk of dropping working jobs if the - // user has not read the release notes - return migrations.CheckNoLegacyJobs(tx.Tx) - }) + // ensure that no legacy job specs are present: we _must_ bail out early if + // so because otherwise we run the risk of dropping working jobs if the + // user has not read the release notes + err = migrations.CheckNoLegacyJobs(ctx, db) if err != nil { return err } @@ -66,14 +63,14 @@ func ensureMigrated(ctx context.Context, db *sql.DB, lggr logger.Logger) error { } // ensure a goose migrations table exists with it's initial v0 - if _, err = goose.GetDBVersion(db); err != nil { + if _, err = goose.GetDBVersionContext(ctx, db); err != nil { return err } // insert records for existing migrations //nolint sql := fmt.Sprintf(`INSERT INTO %s (version_id, is_applied) VALUES ($1, true);`, goose.TableName()) - return pg.SqlTransaction(ctx, db, lggr, func(tx *sqlx.Tx) error { + return sqlutil.TransactDataSource(ctx, sqlxDB, nil, func(tx sqlutil.DataSource) error { for _, name := range names { var id int64 // the first migration doesn't follow the naming convention @@ -92,18 +89,18 @@ func ensureMigrated(ctx context.Context, db *sql.DB, lggr logger.Logger) error { } } - if _, err = db.Exec(sql, id); err != nil { + if _, err = tx.ExecContext(ctx, sql, id); err != nil { return err } } - _, err = db.Exec("DROP TABLE migrations;") + _, err = tx.ExecContext(ctx, "DROP TABLE migrations;") return err }) } -func Migrate(ctx context.Context, db *sql.DB, lggr logger.Logger) error { - if err := ensureMigrated(ctx, db, lggr); err != nil { +func Migrate(ctx context.Context, db *sql.DB) error { + if err := ensureMigrated(ctx, db); err != nil { return err } // WithAllowMissing is necessary when upgrading from 0.10.14 since it @@ -111,8 +108,8 @@ func Migrate(ctx context.Context, db *sql.DB, lggr logger.Logger) error { return goose.Up(db, MIGRATIONS_DIR, goose.WithAllowMissing()) } -func Rollback(ctx context.Context, db *sql.DB, lggr logger.Logger, version null.Int) error { - if err := ensureMigrated(ctx, db, lggr); err != nil { +func Rollback(ctx context.Context, db *sql.DB, version null.Int) error { + if err := ensureMigrated(ctx, db); err != nil { return err } if version.Valid { @@ -121,15 +118,15 @@ func Rollback(ctx context.Context, db *sql.DB, lggr logger.Logger, version null. return goose.Down(db, MIGRATIONS_DIR) } -func Current(ctx context.Context, db *sql.DB, lggr logger.Logger) (int64, error) { - if err := ensureMigrated(ctx, db, lggr); err != nil { +func Current(ctx context.Context, db *sql.DB) (int64, error) { + if err := ensureMigrated(ctx, db); err != nil { return -1, err } return goose.EnsureDBVersion(db) } -func Status(ctx context.Context, db *sql.DB, lggr logger.Logger) error { - if err := ensureMigrated(ctx, db, lggr); err != nil { +func Status(ctx context.Context, db *sql.DB) error { + if err := ensureMigrated(ctx, db); err != nil { return err } return goose.Status(db, MIGRATIONS_DIR) diff --git a/core/store/migrate/migrate_test.go b/core/store/migrate/migrate_test.go index 3c0c2dc2158..8169368eb1f 100644 --- a/core/store/migrate/migrate_test.go +++ b/core/store/migrate/migrate_test.go @@ -21,11 +21,9 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/store/migrate" "github.com/smartcontractkit/chainlink/v2/core/store/models" @@ -79,13 +77,13 @@ func TestMigrate_0100_BootstrapConfigs(t *testing.T) { pipelineORM := pipeline.NewORM(db, lggr, cfg.JobPipeline().MaxSuccessfulRuns()) ctx := testutils.Context(t) - pipelineID, err := pipelineORM.CreateSpec(ctx, nil, pipeline.Pipeline{}, 0) + pipelineID, err := pipelineORM.CreateSpec(ctx, pipeline.Pipeline{}, 0) require.NoError(t, err) - pipelineID2, err := pipelineORM.CreateSpec(ctx, nil, pipeline.Pipeline{}, 0) + pipelineID2, err := pipelineORM.CreateSpec(ctx, pipeline.Pipeline{}, 0) require.NoError(t, err) - nonBootstrapPipelineID, err := pipelineORM.CreateSpec(ctx, nil, pipeline.Pipeline{}, 0) + nonBootstrapPipelineID, err := pipelineORM.CreateSpec(ctx, pipeline.Pipeline{}, 0) require.NoError(t, err) - newFormatBoostrapPipelineID2, err := pipelineORM.CreateSpec(ctx, nil, pipeline.Pipeline{}, 0) + newFormatBoostrapPipelineID2, err := pipelineORM.CreateSpec(ctx, pipeline.Pipeline{}, 0) require.NoError(t, err) // OCR2 struct at migration v0099 @@ -392,25 +390,24 @@ func TestMigrate_101_GenericOCR2(t *testing.T) { func TestMigrate(t *testing.T) { ctx := testutils.Context(t) - lggr := logger.TestLogger(t) _, db := heavyweight.FullTestDBEmptyV2(t, nil) err := goose.UpTo(db.DB, migrationDir, 100) require.NoError(t, err) - err = migrate.Status(ctx, db.DB, lggr) + err = migrate.Status(ctx, db.DB) require.NoError(t, err) - ver, err := migrate.Current(ctx, db.DB, lggr) + ver, err := migrate.Current(ctx, db.DB) require.NoError(t, err) require.Equal(t, int64(100), ver) - err = migrate.Migrate(ctx, db.DB, lggr) + err = migrate.Migrate(ctx, db.DB) require.NoError(t, err) - err = migrate.Rollback(ctx, db.DB, lggr, null.IntFrom(99)) + err = migrate.Rollback(ctx, db.DB, null.IntFrom(99)) require.NoError(t, err) - ver, err = migrate.Current(ctx, db.DB, lggr) + ver, err = migrate.Current(ctx, db.DB) require.NoError(t, err) require.Equal(t, int64(99), ver) } @@ -543,6 +540,7 @@ func TestNoTriggers(t *testing.T) { } func BenchmarkBackfillingRecordsWithMigration202(b *testing.B) { + ctx := testutils.Context(b) previousMigration := int64(201) backfillMigration := int64(202) chainCount := 2 @@ -555,7 +553,6 @@ func BenchmarkBackfillingRecordsWithMigration202(b *testing.B) { err := goose.UpTo(db.DB, migrationDir, previousMigration) require.NoError(b, err) - q := pg.NewQ(db, logger.NullLogger, pgtest.NewQConfig(true)) for j := 0; j < chainCount; j++ { // Insert 100_000 block to database, can't do all at once, so batching by 10k var blocks []logpoller.LogPollerBlock @@ -574,7 +571,7 @@ func BenchmarkBackfillingRecordsWithMigration202(b *testing.B) { end = maxLogsSize } - err = q.ExecQNamed(` + _, err = db.NamedExecContext(ctx, ` INSERT INTO evm.log_poller_blocks (evm_chain_id, block_hash, block_number, finalized_block_number, block_timestamp, created_at) VALUES @@ -600,7 +597,7 @@ func BenchmarkBackfillingRecordsWithMigration202(b *testing.B) { err = goose.DownTo(db.DB, migrationDir, previousMigration) require.NoError(b, err) - err = q.ExecQ(` + _, err = db.ExecContext(ctx, ` UPDATE evm.log_poller_blocks SET finalized_block_number = 0`) require.NoError(b, err) diff --git a/core/store/migrate/migrations/0054_remove_legacy_pipeline.go b/core/store/migrate/migrations/0054_remove_legacy_pipeline.go index 924d32308b8..b5ddcccd89b 100644 --- a/core/store/migrate/migrations/0054_remove_legacy_pipeline.go +++ b/core/store/migrate/migrations/0054_remove_legacy_pipeline.go @@ -32,9 +32,13 @@ func init() { goose.AddMigrationContext(Up54, Down54) } +type queryer interface { + QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row +} + // nolint func Up54(ctx context.Context, tx *sql.Tx) error { - if err := CheckNoLegacyJobs(tx); err != nil { + if err := CheckNoLegacyJobs(ctx, tx); err != nil { return err } if _, err := tx.ExecContext(ctx, up54); err != nil { @@ -49,9 +53,9 @@ func Down54(ctx context.Context, tx *sql.Tx) error { } // CheckNoLegacyJobs ensures that there are no legacy job specs -func CheckNoLegacyJobs(tx *sql.Tx) error { +func CheckNoLegacyJobs(ctx context.Context, ds queryer) error { var count int - if err := tx.QueryRow(`SELECT COUNT(*) FROM job_specs WHERE deleted_at IS NULL`).Scan(&count); err != nil { + if err := ds.QueryRowContext(ctx, `SELECT COUNT(*) FROM job_specs WHERE deleted_at IS NULL`).Scan(&count); err != nil { return err } if count > 0 { diff --git a/core/web/bridge_types_controller.go b/core/web/bridge_types_controller.go index 1c9fd7365f7..c787ca2fb54 100644 --- a/core/web/bridge_types_controller.go +++ b/core/web/bridge_types_controller.go @@ -213,7 +213,7 @@ func (btc *BridgeTypesController) Destroy(c *gin.Context) { jsonAPIError(c, http.StatusInternalServerError, fmt.Errorf("error searching for bridge: %+v", err)) return } - jobsUsingBridge, err := btc.App.JobORM().FindJobIDsWithBridge(name) + jobsUsingBridge, err := btc.App.JobORM().FindJobIDsWithBridge(ctx, name) if err != nil { jsonAPIError(c, http.StatusInternalServerError, fmt.Errorf("error searching for associated v2 jobs: %+v", err)) return diff --git a/core/web/eth_keys_controller_test.go b/core/web/eth_keys_controller_test.go index 09a3eb5fa1e..34cde6f6a64 100644 --- a/core/web/eth_keys_controller_test.go +++ b/core/web/eth_keys_controller_test.go @@ -425,8 +425,7 @@ func TestETHKeysController_ChainSuccess_ResetWithAbandon(t *testing.T) { }) assert.NoError(t, err) - db := app.GetSqlxDB() - txStore := txmgr.NewTxStore(db, logger.TestLogger(t)) + txStore := txmgr.NewTxStore(app.GetDB(), logger.TestLogger(t)) txes, err := txStore.FindTxesByFromAddressAndState(testutils.Context(t), addr, "fatal_error") require.NoError(t, err) diff --git a/core/web/evm_transactions_controller_test.go b/core/web/evm_transactions_controller_test.go index a4dd21c9f03..3eb667bc6f8 100644 --- a/core/web/evm_transactions_controller_test.go +++ b/core/web/evm_transactions_controller_test.go @@ -25,8 +25,8 @@ func TestTransactionsController_Index_Success(t *testing.T) { ctx := testutils.Context(t) require.NoError(t, app.Start(ctx)) - db := app.GetSqlxDB() - txStore := cltest.NewTestTxStore(t, app.GetSqlxDB()) + db := app.GetDB() + txStore := cltest.NewTestTxStore(t, app.GetDB()) ethKeyStore := cltest.NewKeyStore(t, db).Eth() client := app.NewHTTPClient(nil) _, from := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -84,7 +84,7 @@ func TestTransactionsController_Show_Success(t *testing.T) { ctx := testutils.Context(t) require.NoError(t, app.Start(ctx)) - txStore := cltest.NewTestTxStore(t, app.GetSqlxDB()) + txStore := cltest.NewTestTxStore(t, app.GetDB()) client := app.NewHTTPClient(nil) _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) @@ -118,7 +118,7 @@ func TestTransactionsController_Show_NotFound(t *testing.T) { ctx := testutils.Context(t) require.NoError(t, app.Start(ctx)) - txStore := cltest.NewTestTxStore(t, app.GetSqlxDB()) + txStore := cltest.NewTestTxStore(t, app.GetDB()) client := app.NewHTTPClient(nil) _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) tx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, from) diff --git a/core/web/evm_transfer_controller_test.go b/core/web/evm_transfer_controller_test.go index bfac6752f51..fff30a7df31 100644 --- a/core/web/evm_transfer_controller_test.go +++ b/core/web/evm_transfer_controller_test.go @@ -10,9 +10,8 @@ import ( "testing" "time" - "github.com/jmoiron/sqlx" - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -72,7 +71,7 @@ func TestTransfersController_CreateSuccess_From(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Len(t, errors.Errors, 0) - validateTxCount(t, app.GetSqlxDB(), 1) + validateTxCount(t, app.GetDB(), 1) } func TestTransfersController_CreateSuccess_From_WEI(t *testing.T) { @@ -113,7 +112,7 @@ func TestTransfersController_CreateSuccess_From_WEI(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Len(t, errors.Errors, 0) - validateTxCount(t, app.GetSqlxDB(), 1) + validateTxCount(t, app.GetDB(), 1) } func TestTransfersController_CreateSuccess_From_BalanceMonitorDisabled(t *testing.T) { @@ -159,7 +158,7 @@ func TestTransfersController_CreateSuccess_From_BalanceMonitorDisabled(t *testin assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Len(t, errors.Errors, 0) - validateTxCount(t, app.GetSqlxDB(), 1) + validateTxCount(t, app.GetDB(), 1) } func TestTransfersController_TransferZeroAddressError(t *testing.T) { @@ -327,7 +326,7 @@ func TestTransfersController_CreateSuccess_eip1559(t *testing.T) { err = web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, resp), &resource) assert.NoError(t, err) - validateTxCount(t, app.GetSqlxDB(), 1) + validateTxCount(t, app.GetDB(), 1) // check returned data assert.NotEmpty(t, resource.Hash) @@ -398,8 +397,8 @@ func TestTransfersController_FindTxAttempt(t *testing.T) { }) } -func validateTxCount(t *testing.T, db *sqlx.DB, count int) { - txStore := txmgr.NewTxStore(db, logger.TestLogger(t)) +func validateTxCount(t *testing.T, ds sqlutil.DataSource, count int) { + txStore := txmgr.NewTxStore(ds, logger.TestLogger(t)) txes, err := txStore.GetAllTxes(testutils.Context(t)) require.NoError(t, err) diff --git a/core/web/evm_tx_attempts_controller_test.go b/core/web/evm_tx_attempts_controller_test.go index a92c8293a3f..f277f1f37bf 100644 --- a/core/web/evm_tx_attempts_controller_test.go +++ b/core/web/evm_tx_attempts_controller_test.go @@ -20,7 +20,7 @@ func TestTxAttemptsController_Index_Success(t *testing.T) { app := cltest.NewApplicationWithKey(t) require.NoError(t, app.Start(testutils.Context(t))) - txStore := cltest.NewTestTxStore(t, app.GetSqlxDB()) + txStore := cltest.NewTestTxStore(t, app.GetDB()) client := app.NewHTTPClient(nil) _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) diff --git a/core/web/external_initiators_controller_test.go b/core/web/external_initiators_controller_test.go index 3c1425bcfdd..a79909c5864 100644 --- a/core/web/external_initiators_controller_test.go +++ b/core/web/external_initiators_controller_test.go @@ -75,7 +75,7 @@ func TestExternalInitiatorsController_Index(t *testing.T) { client := app.NewHTTPClient(nil) - db := app.GetSqlxDB() + db := app.GetDB() borm := bridges.NewORM(db) eiFoo := cltest.MustInsertExternalInitiatorWithOpts(t, borm, cltest.ExternalInitiatorOpts{ diff --git a/core/web/jobs_controller.go b/core/web/jobs_controller.go index 0808422cca7..5ca00476007 100644 --- a/core/web/jobs_controller.go +++ b/core/web/jobs_controller.go @@ -26,7 +26,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/streams" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" @@ -48,7 +47,7 @@ func (jc *JobsController) Index(c *gin.Context, size, page, offset int) { size = 1000 } - jobs, count, err := jc.App.JobORM().FindJobs(offset, size) + jobs, count, err := jc.App.JobORM().FindJobs(c.Request.Context(), offset, size) if err != nil { jsonAPIError(c, http.StatusInternalServerError, err) return @@ -66,14 +65,15 @@ func (jc *JobsController) Index(c *gin.Context, size, page, offset int) { // Example: // "GET /jobs/:ID" func (jc *JobsController) Show(c *gin.Context) { + ctx := c.Request.Context() var err error jobSpec := job.Job{} if externalJobID, pErr := uuid.Parse(c.Param("ID")); pErr == nil { // Find a job by external job ID - jobSpec, err = jc.App.JobORM().FindJobByExternalJobID(externalJobID, pg.WithParentCtx(c.Request.Context())) + jobSpec, err = jc.App.JobORM().FindJobByExternalJobID(ctx, externalJobID) } else if pErr = jobSpec.SetID(c.Param("ID")); pErr == nil { // Find a job by job ID - jobSpec, err = jc.App.JobORM().FindJobTx(c, jobSpec.ID) + jobSpec, err = jc.App.JobORM().FindJobTx(ctx, jobSpec.ID) } else { jsonAPIError(c, http.StatusUnprocessableEntity, pErr) return @@ -242,7 +242,7 @@ func (jc *JobsController) validateJobSpec(ctx context.Context, tomlString string case job.VRF: jb, err = vrfcommon.ValidatedVRFSpec(tomlString) case job.Webhook: - jb, err = webhook.ValidatedWebhookSpec(tomlString, jc.App.GetExternalInitiatorManager()) + jb, err = webhook.ValidatedWebhookSpec(ctx, tomlString, jc.App.GetExternalInitiatorManager()) case job.BlockhashStore: jb, err = blockhashstore.ValidatedSpec(tomlString) case job.BlockHeaderFeeder: diff --git a/core/web/jobs_controller_test.go b/core/web/jobs_controller_test.go index 9c7b529b6bf..bade8fe293b 100644 --- a/core/web/jobs_controller_test.go +++ b/core/web/jobs_controller_test.go @@ -24,8 +24,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -37,7 +36,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" "github.com/smartcontractkit/chainlink/v2/core/utils/tomlutils" "github.com/smartcontractkit/chainlink/v2/core/web" @@ -129,7 +127,7 @@ func TestJobController_Create_DirectRequest_Fast(t *testing.T) { }(i) } wg.Wait() - cltest.AssertCount(t, app.GetSqlxDB(), "direct_request_specs", int64(n)) + cltest.AssertCount(t, app.GetDB(), "direct_request_specs", int64(n)) } func mustInt32FromString(t *testing.T, s string) int32 { @@ -141,7 +139,7 @@ func mustInt32FromString(t *testing.T, s string) int32 { func TestJobController_Create_HappyPath(t *testing.T) { ctx := testutils.Context(t) app, client := setupJobsControllerTests(t) - b1, b2 := setupBridges(t, app.GetSqlxDB(), app.GetConfig().Database()) + b1, b2 := setupBridges(t, app.GetDB()) require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) var pks []vrfkey.KeyV2 var k []p2pkey.KeyV2 @@ -220,7 +218,8 @@ func TestJobController_Create_HappyPath(t *testing.T) { // services failed to start require.Contains(t, errs.Errors[0].Detail, "no contract code at given address") // but the job should still exist - jb, err := jorm.FindJobByExternalJobID(uuid.MustParse(nameAndExternalJobID)) + ctx := testutils.Context(t) + jb, err := jorm.FindJobByExternalJobID(ctx, uuid.MustParse(nameAndExternalJobID)) require.NoError(t, err) require.NotNil(t, jb.KeeperSpec) @@ -333,7 +332,8 @@ func TestJobController_Create_HappyPath(t *testing.T) { // services failed to start require.Contains(t, errs.Errors[0].Detail, "no contract code at given address") // but the job should still exist - jb, err := jorm.FindJobByExternalJobID(uuid.MustParse(nameAndExternalJobID)) + ctx := testutils.Context(t) + jb, err := jorm.FindJobByExternalJobID(ctx, uuid.MustParse(nameAndExternalJobID)) require.NoError(t, err) require.NotNil(t, jb.FluxMonitorSpec) @@ -481,8 +481,8 @@ func TestJobsController_Create_WebhookSpec(t *testing.T) { app := cltest.NewApplicationEVMDisabled(t) require.NoError(t, app.Start(testutils.Context(t))) - _, fetchBridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) - _, submitBridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) + _, fetchBridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) + _, submitBridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) client := app.NewHTTPClient(nil) @@ -620,10 +620,10 @@ func TestJobsController_Update_HappyPath(t *testing.T) { app := cltest.NewApplicationWithConfigAndKey(t, cfg, cltest.DefaultP2PKey) require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) - _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) - _, bridge2 := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) + _, bridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) + _, bridge2 := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) client := app.NewHTTPClient(nil) @@ -639,16 +639,16 @@ func TestJobsController_Update_HappyPath(t *testing.T) { // BCF-2095 // disable fkey checks until the end of the test transaction require.NoError(t, utils.JustError( - app.GetSqlxDB().Exec(`SET CONSTRAINTS job_spec_errors_v2_job_id_fkey DEFERRED`))) + app.GetDB().ExecContext(ctx, `SET CONSTRAINTS job_spec_errors_v2_job_id_fkey DEFERRED`))) var ocrSpec job.OCROracleSpec err = toml.Unmarshal([]byte(ocrspec.Toml()), &ocrSpec) require.NoError(t, err) jb.OCROracleSpec = &ocrSpec jb.OCROracleSpec.TransmitterAddress = &app.Keys[0].EIP55Address - err = app.AddJobV2(testutils.Context(t), &jb) + err = app.AddJobV2(ctx, &jb) require.NoError(t, err) - dbJb, err := app.JobORM().FindJob(testutils.Context(t), jb.ID) + dbJb, err := app.JobORM().FindJob(ctx, jb.ID) require.NoError(t, err) require.Equal(t, dbJb.Name.String, ocrspec.Name) @@ -666,7 +666,7 @@ func TestJobsController_Update_HappyPath(t *testing.T) { response, cleanup := client.Put("/v2/jobs/"+fmt.Sprintf("%v", jb.ID), bytes.NewReader(body)) t.Cleanup(cleanup) - dbJb, err = app.JobORM().FindJob(testutils.Context(t), jb.ID) + dbJb, err = app.JobORM().FindJob(ctx, jb.ID) require.NoError(t, err) require.Equal(t, dbJb.Name.String, updatedSpec.Name) @@ -686,8 +686,8 @@ func TestJobsController_Update_NonExistentID(t *testing.T) { require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) require.NoError(t, app.Start(ctx)) - _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) - _, bridge2 := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) + _, bridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) + _, bridge2 := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) client := app.NewHTTPClient(nil) @@ -754,9 +754,9 @@ func runDirectRequestJobSpecAssertions(t *testing.T, ereJobSpecFromFile job.Job, assert.Contains(t, ereJobSpecFromServer.DirectRequestSpec.UpdatedAt.String(), "20") } -func setupBridges(t *testing.T, db *sqlx.DB, cfg pg.QConfig) (b1, b2 string) { - _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) - _, bridge2 := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) +func setupBridges(t *testing.T, ds sqlutil.DataSource) (b1, b2 string) { + _, bridge := cltest.MustCreateBridge(t, ds, cltest.BridgeOpts{}) + _, bridge2 := cltest.MustCreateBridge(t, ds, cltest.BridgeOpts{}) return bridge.Name.String(), bridge2.Name.String() } @@ -800,8 +800,8 @@ func setupJobSpecsControllerTestsWithJobs(t *testing.T) (*cltest.TestApplication require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) require.NoError(t, app.Start(ctx)) - _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) - _, bridge2 := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) + _, bridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) + _, bridge2 := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{}) client := app.NewHTTPClient(nil) diff --git a/core/web/loader/feeds_manager.go b/core/web/loader/feeds_manager.go index fb894d38b6e..a29d510a09d 100644 --- a/core/web/loader/feeds_manager.go +++ b/core/web/loader/feeds_manager.go @@ -14,7 +14,7 @@ type feedsBatcher struct { app chainlink.Application } -func (b *feedsBatcher) loadByIDs(_ context.Context, keys dataloader.Keys) []*dataloader.Result { +func (b *feedsBatcher) loadByIDs(ctx context.Context, keys dataloader.Keys) []*dataloader.Result { // Create a map for remembering the order of keys passed in keyOrder := make(map[string]int, len(keys)) // Collect the keys to search for @@ -28,7 +28,7 @@ func (b *feedsBatcher) loadByIDs(_ context.Context, keys dataloader.Keys) []*dat } // Fetch the feeds managers - managers, err := b.app.GetFeedsService().ListManagersByIDs(managersIDs) + managers, err := b.app.GetFeedsService().ListManagersByIDs(ctx, managersIDs) if err != nil { return []*dataloader.Result{{Data: nil, Error: err}} } diff --git a/core/web/loader/feeds_manager_chain_config.go b/core/web/loader/feeds_manager_chain_config.go index 89d35919fd1..661edc33219 100644 --- a/core/web/loader/feeds_manager_chain_config.go +++ b/core/web/loader/feeds_manager_chain_config.go @@ -14,10 +14,10 @@ type feedsManagerChainConfigBatcher struct { app chainlink.Application } -func (b *feedsManagerChainConfigBatcher) loadByManagerIDs(_ context.Context, keys dataloader.Keys) []*dataloader.Result { +func (b *feedsManagerChainConfigBatcher) loadByManagerIDs(ctx context.Context, keys dataloader.Keys) []*dataloader.Result { ids, keyOrder := keyOrderInt64(keys) - cfgs, err := b.app.GetFeedsService().ListChainConfigsByManagerIDs(ids) + cfgs, err := b.app.GetFeedsService().ListChainConfigsByManagerIDs(ctx, ids) if err != nil { return []*dataloader.Result{{Data: nil, Error: err}} } diff --git a/core/web/loader/job.go b/core/web/loader/job.go index 11eb2c76814..a37c2809625 100644 --- a/core/web/loader/job.go +++ b/core/web/loader/job.go @@ -16,7 +16,7 @@ type jobBatcher struct { app chainlink.Application } -func (b *jobBatcher) loadByExternalJobIDs(_ context.Context, keys dataloader.Keys) []*dataloader.Result { +func (b *jobBatcher) loadByExternalJobIDs(ctx context.Context, keys dataloader.Keys) []*dataloader.Result { // Create a map for remembering the order of keys passed in keyOrder := make(map[string]int, len(keys)) // Collect the keys to search for @@ -33,7 +33,7 @@ func (b *jobBatcher) loadByExternalJobIDs(_ context.Context, keys dataloader.Key // Fetch the jobs var jobs []job.Job for _, id := range jobIDs { - job, err := b.app.JobORM().FindJobByExternalJobID(id) + job, err := b.app.JobORM().FindJobByExternalJobID(ctx, id) if err != nil { return []*dataloader.Result{{Data: nil, Error: err}} @@ -63,7 +63,7 @@ func (b *jobBatcher) loadByExternalJobIDs(_ context.Context, keys dataloader.Key return results } -func (b *jobBatcher) loadByPipelineSpecIDs(_ context.Context, keys dataloader.Keys) []*dataloader.Result { +func (b *jobBatcher) loadByPipelineSpecIDs(ctx context.Context, keys dataloader.Keys) []*dataloader.Result { // Create a map for remembering the order of keys passed in keyOrder := make(map[string]int, len(keys)) // Collect the keys to search for @@ -77,7 +77,7 @@ func (b *jobBatcher) loadByPipelineSpecIDs(_ context.Context, keys dataloader.Ke } // Fetch the jobs - jobs, err := b.app.JobORM().FindJobsByPipelineSpecIDs(plSpecIDs) + jobs, err := b.app.JobORM().FindJobsByPipelineSpecIDs(ctx, plSpecIDs) if err != nil { return []*dataloader.Result{{Data: nil, Error: err}} } diff --git a/core/web/loader/job_proposal.go b/core/web/loader/job_proposal.go index ac24e620f47..17fb6bc67c2 100644 --- a/core/web/loader/job_proposal.go +++ b/core/web/loader/job_proposal.go @@ -14,7 +14,7 @@ type jobProposalBatcher struct { app chainlink.Application } -func (b *jobProposalBatcher) loadByManagersIDs(_ context.Context, keys dataloader.Keys) []*dataloader.Result { +func (b *jobProposalBatcher) loadByManagersIDs(ctx context.Context, keys dataloader.Keys) []*dataloader.Result { // Create a map for remembering the order of keys passed in keyOrder := make(map[string]int, len(keys)) // Collect the keys to search for @@ -28,7 +28,7 @@ func (b *jobProposalBatcher) loadByManagersIDs(_ context.Context, keys dataloade keyOrder[key.String()] = ix } - jps, err := b.app.GetFeedsService().ListJobProposalsByManagersIDs(mgrsIDs) + jps, err := b.app.GetFeedsService().ListJobProposalsByManagersIDs(ctx, mgrsIDs) if err != nil { return []*dataloader.Result{{Data: nil, Error: err}} } diff --git a/core/web/loader/job_proposal_spec.go b/core/web/loader/job_proposal_spec.go index bb6720903dc..bff112268f8 100644 --- a/core/web/loader/job_proposal_spec.go +++ b/core/web/loader/job_proposal_spec.go @@ -14,10 +14,10 @@ type jobProposalSpecBatcher struct { app chainlink.Application } -func (b *jobProposalSpecBatcher) loadByJobProposalsIDs(_ context.Context, keys dataloader.Keys) []*dataloader.Result { +func (b *jobProposalSpecBatcher) loadByJobProposalsIDs(ctx context.Context, keys dataloader.Keys) []*dataloader.Result { ids, keyOrder := keyOrderInt64(keys) - specs, err := b.app.GetFeedsService().ListSpecsByJobProposalIDs(ids) + specs, err := b.app.GetFeedsService().ListSpecsByJobProposalIDs(ctx, ids) if err != nil { return []*dataloader.Result{{Data: nil, Error: err}} } diff --git a/core/web/loader/job_run.go b/core/web/loader/job_run.go index 691b27a3511..4367eec2c78 100644 --- a/core/web/loader/job_run.go +++ b/core/web/loader/job_run.go @@ -14,7 +14,7 @@ type jobRunBatcher struct { app chainlink.Application } -func (b *jobRunBatcher) loadByIDs(_ context.Context, keys dataloader.Keys) []*dataloader.Result { +func (b *jobRunBatcher) loadByIDs(ctx context.Context, keys dataloader.Keys) []*dataloader.Result { // Create a map for remembering the order of keys passed in keyOrder := make(map[string]int, len(keys)) // Collect the keys to search for @@ -29,7 +29,7 @@ func (b *jobRunBatcher) loadByIDs(_ context.Context, keys dataloader.Keys) []*da } // Fetch the runs - runs, err := b.app.JobORM().FindPipelineRunsByIDs(runIDs) + runs, err := b.app.JobORM().FindPipelineRunsByIDs(ctx, runIDs) if err != nil { return []*dataloader.Result{{Data: nil, Error: err}} } diff --git a/core/web/loader/job_spec_errors.go b/core/web/loader/job_spec_errors.go index 5ef23154d2e..5d558c52ec5 100644 --- a/core/web/loader/job_spec_errors.go +++ b/core/web/loader/job_spec_errors.go @@ -7,7 +7,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/utils/stringutils" ) @@ -29,7 +28,7 @@ func (b *jobSpecErrorsBatcher) loadByJobIDs(ctx context.Context, keys dataloader keyOrder[key.String()] = ix } - specErrors, err := b.app.JobORM().FindSpecErrorsByJobIDs(jobIDs, pg.WithParentCtx(ctx)) + specErrors, err := b.app.JobORM().FindSpecErrorsByJobIDs(ctx, jobIDs) if err != nil { return []*dataloader.Result{{Data: nil, Error: err}} } diff --git a/core/web/loader/loader_test.go b/core/web/loader/loader_test.go index d12a10a9e52..5e22c9afef6 100644 --- a/core/web/loader/loader_test.go +++ b/core/web/loader/loader_test.go @@ -125,7 +125,7 @@ func TestLoader_FeedsManagers(t *testing.T) { Name: "manager 3", } - fsvc.On("ListManagersByIDs", []int64{3, 1, 2, 5}).Return([]feeds.FeedsManager{ + fsvc.On("ListManagersByIDs", mock.Anything, []int64{3, 1, 2, 5}).Return([]feeds.FeedsManager{ mgr1, mgr2, mgr3, }, nil) app.On("GetFeedsService").Return(fsvc) @@ -167,7 +167,7 @@ func TestLoader_JobProposals(t *testing.T) { Status: feeds.JobProposalStatusRejected, } - fsvc.On("ListJobProposalsByManagersIDs", []int64{3, 1, 2}).Return([]feeds.JobProposal{ + fsvc.On("ListJobProposalsByManagersIDs", mock.Anything, []int64{3, 1, 2}).Return([]feeds.JobProposal{ jp1, jp3, jp2, }, nil) app.On("GetFeedsService").Return(fsvc) @@ -194,7 +194,7 @@ func TestLoader_JobRuns(t *testing.T) { run2 := pipeline.Run{ID: int64(2)} run3 := pipeline.Run{ID: int64(3)} - jobsORM.On("FindPipelineRunsByIDs", []int64{3, 1, 2}).Return([]pipeline.Run{ + jobsORM.On("FindPipelineRunsByIDs", mock.Anything, []int64{3, 1, 2}).Return([]pipeline.Run{ run3, run1, run2, }, nil) app.On("JobORM").Return(jobsORM) @@ -224,7 +224,7 @@ func TestLoader_JobsByPipelineSpecIDs(t *testing.T) { job2 := job.Job{ID: int32(3), PipelineSpecID: int32(2)} job3 := job.Job{ID: int32(4), PipelineSpecID: int32(3)} - jobsORM.On("FindJobsByPipelineSpecIDs", []int32{3, 1, 2}).Return([]job.Job{ + jobsORM.On("FindJobsByPipelineSpecIDs", mock.Anything, []int32{3, 1, 2}).Return([]job.Job{ job1, job2, job3, }, nil) app.On("JobORM").Return(jobsORM) @@ -247,7 +247,7 @@ func TestLoader_JobsByPipelineSpecIDs(t *testing.T) { app := coremocks.NewApplication(t) ctx := InjectDataloader(testutils.Context(t), app) - jobsORM.On("FindJobsByPipelineSpecIDs", []int32{3, 1, 2}).Return([]job.Job{}, sql.ErrNoRows) + jobsORM.On("FindJobsByPipelineSpecIDs", mock.Anything, []int32{3, 1, 2}).Return([]job.Job{}, sql.ErrNoRows) app.On("JobORM").Return(jobsORM) batcher := jobBatcher{app} @@ -274,7 +274,7 @@ func TestLoader_JobsByExternalJobIDs(t *testing.T) { ejID := uuid.New() job := job.Job{ID: int32(2), ExternalJobID: ejID} - jobsORM.On("FindJobByExternalJobID", ejID).Return(job, nil) + jobsORM.On("FindJobByExternalJobID", mock.Anything, ejID).Return(job, nil) app.On("JobORM").Return(jobsORM) batcher := jobBatcher{app} @@ -335,7 +335,7 @@ func TestLoader_SpecErrorsByJobID(t *testing.T) { specErr2 := job.SpecError{ID: int64(3), JobID: int32(2)} specErr3 := job.SpecError{ID: int64(4), JobID: int32(3)} - jobsORM.On("FindSpecErrorsByJobIDs", []int32{3, 1, 2}, mock.Anything).Return([]job.SpecError{ + jobsORM.On("FindSpecErrorsByJobIDs", mock.Anything, []int32{3, 1, 2}, mock.Anything).Return([]job.SpecError{ specErr1, specErr2, specErr3, }, nil) app.On("JobORM").Return(jobsORM) @@ -358,7 +358,7 @@ func TestLoader_SpecErrorsByJobID(t *testing.T) { app := coremocks.NewApplication(t) ctx := InjectDataloader(testutils.Context(t), app) - jobsORM.On("FindSpecErrorsByJobIDs", []int32{3, 1, 2}, mock.Anything).Return([]job.SpecError{}, sql.ErrNoRows) + jobsORM.On("FindSpecErrorsByJobIDs", mock.Anything, []int32{3, 1, 2}, mock.Anything).Return([]job.SpecError{}, sql.ErrNoRows) app.On("JobORM").Return(jobsORM) batcher := jobSpecErrorsBatcher{app} diff --git a/core/web/pipeline_job_spec_errors_controller_test.go b/core/web/pipeline_job_spec_errors_controller_test.go index 8ec77a84f05..9729bfac51d 100644 --- a/core/web/pipeline_job_spec_errors_controller_test.go +++ b/core/web/pipeline_job_spec_errors_controller_test.go @@ -17,7 +17,8 @@ func TestPipelineJobSpecErrorsController_Delete_2(t *testing.T) { description := "job spec error description" - require.NoError(t, app.JobORM().RecordError(jID, description)) + ctx := testutils.Context(t) + require.NoError(t, app.JobORM().RecordError(ctx, jID, description)) // FindJob -> find error j, err := app.JobORM().FindJob(testutils.Context(t), jID) diff --git a/core/web/pipeline_runs_controller.go b/core/web/pipeline_runs_controller.go index 1bd52b021c3..099f824e0c3 100644 --- a/core/web/pipeline_runs_controller.go +++ b/core/web/pipeline_runs_controller.go @@ -40,8 +40,9 @@ func (prc *PipelineRunsController) Index(c *gin.Context, size, page, offset int) var count int var err error + ctx := c.Request.Context() if id == "" { - pipelineRuns, count, err = prc.App.JobORM().PipelineRuns(nil, offset, size) + pipelineRuns, count, err = prc.App.JobORM().PipelineRuns(ctx, nil, offset, size) } else { jobSpec := job.Job{} err = jobSpec.SetID(c.Param("ID")) @@ -50,7 +51,7 @@ func (prc *PipelineRunsController) Index(c *gin.Context, size, page, offset int) return } - pipelineRuns, count, err = prc.App.JobORM().PipelineRuns(&jobSpec.ID, offset, size) + pipelineRuns, count, err = prc.App.JobORM().PipelineRuns(ctx, &jobSpec.ID, offset, size) } if err != nil { @@ -113,13 +114,13 @@ func (prc *PipelineRunsController) Create(c *gin.Context) { // Is it a UUID? Then process it as a webhook job jobUUID, err := uuid.Parse(idStr) if err == nil { - canRun, err2 := authorizer.CanRun(c.Request.Context(), prc.App.GetConfig().JobPipeline(), jobUUID) + canRun, err2 := authorizer.CanRun(ctx, prc.App.GetConfig().JobPipeline(), jobUUID) if err2 != nil { jsonAPIError(c, http.StatusInternalServerError, err2) return } if canRun { - jobRunID, err3 := prc.App.RunWebhookJobV2(c.Request.Context(), jobUUID, string(bodyBytes), jsonserializable.JSONSerializable{}) + jobRunID, err3 := prc.App.RunWebhookJobV2(ctx, jobUUID, string(bodyBytes), jsonserializable.JSONSerializable{}) if errors.Is(err3, webhook.ErrJobNotExists) { jsonAPIError(c, http.StatusNotFound, err3) return @@ -141,7 +142,7 @@ func (prc *PipelineRunsController) Create(c *gin.Context) { jobID64, err := strconv.ParseInt(idStr, 10, 32) if err == nil { jobID = int32(jobID64) - jobRunID, err := prc.App.RunJobV2(c.Request.Context(), jobID, nil) + jobRunID, err := prc.App.RunJobV2(ctx, jobID, nil) if err != nil { jsonAPIError(c, http.StatusInternalServerError, err) return diff --git a/core/web/pipeline_runs_controller_test.go b/core/web/pipeline_runs_controller_test.go index f6b4291a34f..e123df2bdb3 100644 --- a/core/web/pipeline_runs_controller_test.go +++ b/core/web/pipeline_runs_controller_test.go @@ -33,6 +33,7 @@ import ( func TestPipelineRunsController_CreateWithBody_HappyPath(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.JobPipeline.HTTPRequest.DefaultTimeout = commonconfig.MustNewDuration(2 * time.Second) @@ -50,13 +51,13 @@ func TestPipelineRunsController_CreateWithBody_HappyPath(t *testing.T) { require.Equal(t, `{"result":"12345"}`, string(bs)) }) - _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{URL: mockServer.URL}) + _, bridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{URL: mockServer.URL}) // Add the job uuid := uuid.New() { tomlStr := fmt.Sprintf(testspecs.WebhookSpecWithBodyTemplate, uuid, bridge.Name.String()) - jb, err := webhook.ValidatedWebhookSpec(tomlStr, app.GetExternalInitiatorManager()) + jb, err := webhook.ValidatedWebhookSpec(ctx, tomlStr, app.GetExternalInitiatorManager()) require.NoError(t, err) err = app.AddJobV2(testutils.Context(t), &jb) @@ -88,6 +89,7 @@ func TestPipelineRunsController_CreateWithBody_HappyPath(t *testing.T) { func TestPipelineRunsController_CreateNoBody_HappyPath(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.JobPipeline.HTTPRequest.DefaultTimeout = commonconfig.MustNewDuration(2 * time.Second) @@ -100,7 +102,7 @@ func TestPipelineRunsController_CreateNoBody_HappyPath(t *testing.T) { // Setup the bridges mockServer := cltest.NewHTTPMockServer(t, 200, "POST", `{"data":{"result":"123.45"}}`) - _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{URL: mockServer.URL}) + _, bridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{URL: mockServer.URL}) mockServer = cltest.NewHTTPMockServerWithRequest(t, 200, `{}`, func(r *http.Request) { defer r.Body.Close() @@ -109,13 +111,13 @@ func TestPipelineRunsController_CreateNoBody_HappyPath(t *testing.T) { require.Equal(t, `{"result":"12345"}`, string(bs)) }) - _, submitBridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{URL: mockServer.URL}) + _, submitBridge := cltest.MustCreateBridge(t, app.GetDB(), cltest.BridgeOpts{URL: mockServer.URL}) // Add the job uuid := uuid.New() { tomlStr := testspecs.GetWebhookSpecNoBody(uuid, bridge.Name.String(), submitBridge.Name.String()) - jb, err := webhook.ValidatedWebhookSpec(tomlStr, app.GetExternalInitiatorManager()) + jb, err := webhook.ValidatedWebhookSpec(ctx, tomlStr, app.GetExternalInitiatorManager()) require.NoError(t, err) err = app.AddJobV2(testutils.Context(t), &jb) diff --git a/core/web/resolver/bridge_test.go b/core/web/resolver/bridge_test.go index 706d3fb6d5a..2244ddf3dac 100644 --- a/core/web/resolver/bridge_test.go +++ b/core/web/resolver/bridge_test.go @@ -418,7 +418,7 @@ func Test_DeleteBridgeMutation(t *testing.T) { f.Mocks.bridgeORM.On("FindBridge", mock.Anything, name).Return(bridge, nil) f.Mocks.bridgeORM.On("DeleteBridgeType", mock.Anything, &bridge).Return(nil) - f.Mocks.jobORM.On("FindJobIDsWithBridge", name.String()).Return([]int32{}, nil) + f.Mocks.jobORM.On("FindJobIDsWithBridge", mock.Anything, name.String()).Return([]int32{}, nil) f.App.On("JobORM").Return(f.Mocks.jobORM) f.App.On("BridgeORM").Return(f.Mocks.bridgeORM) }, @@ -481,7 +481,7 @@ func Test_DeleteBridgeMutation(t *testing.T) { }, before: func(f *gqlTestFramework) { f.Mocks.bridgeORM.On("FindBridge", mock.Anything, name).Return(bridges.BridgeType{}, nil) - f.Mocks.jobORM.On("FindJobIDsWithBridge", name.String()).Return([]int32{1}, nil) + f.Mocks.jobORM.On("FindJobIDsWithBridge", mock.Anything, name.String()).Return([]int32{1}, nil) f.App.On("BridgeORM").Return(f.Mocks.bridgeORM) f.App.On("JobORM").Return(f.Mocks.jobORM) }, diff --git a/core/web/resolver/feeds_manager_chain_config_test.go b/core/web/resolver/feeds_manager_chain_config_test.go index ae869b50874..31208aa0581 100644 --- a/core/web/resolver/feeds_manager_chain_config_test.go +++ b/core/web/resolver/feeds_manager_chain_config_test.go @@ -101,7 +101,7 @@ func Test_CreateFeedsManagerChainConfig(t *testing.T) { }, }, }).Return(cfgID, nil) - f.Mocks.feedsSvc.On("GetChainConfig", cfgID).Return(&feeds.ChainConfig{ + f.Mocks.feedsSvc.On("GetChainConfig", mock.Anything, cfgID).Return(&feeds.ChainConfig{ ID: cfgID, ChainType: feeds.ChainTypeEVM, ChainID: chainID, @@ -164,7 +164,7 @@ func Test_CreateFeedsManagerChainConfig(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("CreateChainConfig", mock.Anything, mock.IsType(feeds.ChainConfig{})).Return(cfgID, nil) - f.Mocks.feedsSvc.On("GetChainConfig", cfgID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetChainConfig", mock.Anything, cfgID).Return(nil, sql.ErrNoRows) }, query: mutation, variables: variables, @@ -211,7 +211,7 @@ func Test_DeleteFeedsManagerChainConfig(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) - f.Mocks.feedsSvc.On("GetChainConfig", cfgID).Return(&feeds.ChainConfig{ + f.Mocks.feedsSvc.On("GetChainConfig", mock.Anything, cfgID).Return(&feeds.ChainConfig{ ID: cfgID, }, nil) f.Mocks.feedsSvc.On("DeleteChainConfig", mock.Anything, cfgID).Return(cfgID, nil) @@ -232,7 +232,7 @@ func Test_DeleteFeedsManagerChainConfig(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) - f.Mocks.feedsSvc.On("GetChainConfig", cfgID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetChainConfig", mock.Anything, cfgID).Return(nil, sql.ErrNoRows) }, query: mutation, variables: variables, @@ -249,7 +249,7 @@ func Test_DeleteFeedsManagerChainConfig(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) - f.Mocks.feedsSvc.On("GetChainConfig", cfgID).Return(&feeds.ChainConfig{ + f.Mocks.feedsSvc.On("GetChainConfig", mock.Anything, cfgID).Return(&feeds.ChainConfig{ ID: cfgID, }, nil) f.Mocks.feedsSvc.On("DeleteChainConfig", mock.Anything, cfgID).Return(int64(0), sql.ErrNoRows) @@ -352,7 +352,7 @@ func Test_UpdateFeedsManagerChainConfig(t *testing.T) { }, }, }).Return(cfgID, nil) - f.Mocks.feedsSvc.On("GetChainConfig", cfgID).Return(&feeds.ChainConfig{ + f.Mocks.feedsSvc.On("GetChainConfig", mock.Anything, cfgID).Return(&feeds.ChainConfig{ ID: cfgID, AccountAddress: accountAddr, AdminAddress: adminAddr, @@ -413,7 +413,7 @@ func Test_UpdateFeedsManagerChainConfig(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("UpdateChainConfig", mock.Anything, mock.IsType(feeds.ChainConfig{})).Return(cfgID, nil) - f.Mocks.feedsSvc.On("GetChainConfig", cfgID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetChainConfig", mock.Anything, cfgID).Return(nil, sql.ErrNoRows) }, query: mutation, variables: variables, diff --git a/core/web/resolver/feeds_manager_test.go b/core/web/resolver/feeds_manager_test.go index 84558090da5..a3ea80a6443 100644 --- a/core/web/resolver/feeds_manager_test.go +++ b/core/web/resolver/feeds_manager_test.go @@ -42,14 +42,14 @@ func Test_FeedsManagers(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) - f.Mocks.feedsSvc.On("ListJobProposalsByManagersIDs", []int64{1}).Return([]feeds.JobProposal{ + f.Mocks.feedsSvc.On("ListJobProposalsByManagersIDs", mock.Anything, []int64{1}).Return([]feeds.JobProposal{ { ID: int64(100), FeedsManagerID: int64(1), Status: feeds.JobProposalStatusApproved, }, }, nil) - f.Mocks.feedsSvc.On("ListManagers").Return([]feeds.FeedsManager{ + f.Mocks.feedsSvc.On("ListManagers", mock.Anything).Return([]feeds.FeedsManager{ { ID: 1, Name: "manager1", @@ -115,7 +115,7 @@ func Test_FeedsManager(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) - f.Mocks.feedsSvc.On("GetManager", mgrID).Return(&feeds.FeedsManager{ + f.Mocks.feedsSvc.On("GetManager", mock.Anything, mgrID).Return(&feeds.FeedsManager{ ID: mgrID, Name: "manager1", URI: "localhost:2000", @@ -142,7 +142,7 @@ func Test_FeedsManager(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) - f.Mocks.feedsSvc.On("GetManager", mgrID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetManager", mock.Anything, mgrID).Return(nil, sql.ErrNoRows) }, query: query, result: ` @@ -219,7 +219,7 @@ func Test_CreateFeedsManager(t *testing.T) { URI: uri, PublicKey: *pubKey, }).Return(mgrID, nil) - f.Mocks.feedsSvc.On("GetManager", mgrID).Return(&feeds.FeedsManager{ + f.Mocks.feedsSvc.On("GetManager", mock.Anything, mgrID).Return(&feeds.FeedsManager{ ID: mgrID, Name: name, URI: uri, @@ -269,7 +269,7 @@ func Test_CreateFeedsManager(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("RegisterManager", mock.Anything, mock.IsType(feeds.RegisterManagerParams{})).Return(mgrID, nil) - f.Mocks.feedsSvc.On("GetManager", mgrID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetManager", mock.Anything, mgrID).Return(nil, sql.ErrNoRows) }, query: mutation, variables: variables, @@ -366,7 +366,7 @@ func Test_UpdateFeedsManager(t *testing.T) { URI: uri, PublicKey: *pubKey, }).Return(nil) - f.Mocks.feedsSvc.On("GetManager", mgrID).Return(&feeds.FeedsManager{ + f.Mocks.feedsSvc.On("GetManager", mock.Anything, mgrID).Return(&feeds.FeedsManager{ ID: mgrID, Name: name, URI: uri, @@ -397,7 +397,7 @@ func Test_UpdateFeedsManager(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("UpdateManager", mock.Anything, mock.IsType(feeds.FeedsManager{})).Return(nil) - f.Mocks.feedsSvc.On("GetManager", mgrID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetManager", mock.Anything, mgrID).Return(nil, sql.ErrNoRows) }, query: mutation, variables: variables, diff --git a/core/web/resolver/job.go b/core/web/resolver/job.go index cb79b0c6e63..e9855fdb8fe 100644 --- a/core/web/resolver/job.go +++ b/core/web/resolver/job.go @@ -113,7 +113,7 @@ func (r *JobResolver) Runs(ctx context.Context, args struct { limit = 100 } - ids, err := r.app.JobORM().FindPipelineRunIDsByJobID(r.j.ID, offset, limit) + ids, err := r.app.JobORM().FindPipelineRunIDsByJobID(ctx, r.j.ID, offset, limit) if err != nil { return nil, err } @@ -123,7 +123,7 @@ func (r *JobResolver) Runs(ctx context.Context, args struct { return nil, err } - count, err := r.app.JobORM().CountPipelineRunsByJobID(r.j.ID) + count, err := r.app.JobORM().CountPipelineRunsByJobID(ctx, r.j.ID) if err != nil { return nil, err } diff --git a/core/web/resolver/job_error_test.go b/core/web/resolver/job_error_test.go index 30d06289ed6..69899a3ec47 100644 --- a/core/web/resolver/job_error_test.go +++ b/core/web/resolver/job_error_test.go @@ -29,10 +29,10 @@ func TestResolver_JobErrors(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ ID: int32(1), }, nil) - f.Mocks.jobORM.On("FindSpecErrorsByJobIDs", []int32{1}, mock.Anything).Return([]job.SpecError{ + f.Mocks.jobORM.On("FindSpecErrorsByJobIDs", mock.Anything, []int32{1}, mock.Anything).Return([]job.SpecError{ { ID: errorID, Description: "no contract code at given address", @@ -124,7 +124,7 @@ func TestResolver_DismissJobError(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindSpecError", id).Return(job.SpecError{ + f.Mocks.jobORM.On("FindSpecError", mock.Anything, id).Return(job.SpecError{ ID: id, Occurrences: 5, Description: "test-description", @@ -141,7 +141,7 @@ func TestResolver_DismissJobError(t *testing.T) { name: "not found on FindSpecError()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindSpecError", id).Return(job.SpecError{}, sql.ErrNoRows) + f.Mocks.jobORM.On("FindSpecError", mock.Anything, id).Return(job.SpecError{}, sql.ErrNoRows) f.App.On("JobORM").Return(f.Mocks.jobORM) }, query: mutation, @@ -159,7 +159,7 @@ func TestResolver_DismissJobError(t *testing.T) { name: "not found on DismissError()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindSpecError", id).Return(job.SpecError{}, nil) + f.Mocks.jobORM.On("FindSpecError", mock.Anything, id).Return(job.SpecError{}, nil) f.Mocks.jobORM.On("DismissError", mock.Anything, id).Return(sql.ErrNoRows) f.App.On("JobORM").Return(f.Mocks.jobORM) }, @@ -178,7 +178,7 @@ func TestResolver_DismissJobError(t *testing.T) { name: "generic error on FindSpecError()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindSpecError", id).Return(job.SpecError{}, gError) + f.Mocks.jobORM.On("FindSpecError", mock.Anything, id).Return(job.SpecError{}, gError) f.App.On("JobORM").Return(f.Mocks.jobORM) }, query: mutation, @@ -197,7 +197,7 @@ func TestResolver_DismissJobError(t *testing.T) { name: "generic error on DismissError()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindSpecError", id).Return(job.SpecError{}, nil) + f.Mocks.jobORM.On("FindSpecError", mock.Anything, id).Return(job.SpecError{}, nil) f.Mocks.jobORM.On("DismissError", mock.Anything, id).Return(gError) f.App.On("JobORM").Return(f.Mocks.jobORM) }, diff --git a/core/web/resolver/job_proposal_spec_test.go b/core/web/resolver/job_proposal_spec_test.go index 2681129b2ae..c65702c5622 100644 --- a/core/web/resolver/job_proposal_spec_test.go +++ b/core/web/resolver/job_proposal_spec_test.go @@ -53,7 +53,7 @@ func TestResolver_ApproveJobProposalSpec(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("ApproveSpec", mock.Anything, specID, false).Return(nil) - f.Mocks.feedsSvc.On("GetSpec", specID).Return(&feeds.JobProposalSpec{ + f.Mocks.feedsSvc.On("GetSpec", mock.Anything, specID).Return(&feeds.JobProposalSpec{ ID: specID, }, nil) }, @@ -84,7 +84,7 @@ func TestResolver_ApproveJobProposalSpec(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("ApproveSpec", mock.Anything, specID, false).Return(nil) - f.Mocks.feedsSvc.On("GetSpec", specID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetSpec", mock.Anything, specID).Return(nil, sql.ErrNoRows) }, query: mutation, variables: variables, @@ -157,7 +157,7 @@ func TestResolver_CancelJobProposalSpec(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("CancelSpec", mock.Anything, specID).Return(nil) - f.Mocks.feedsSvc.On("GetSpec", specID).Return(&feeds.JobProposalSpec{ + f.Mocks.feedsSvc.On("GetSpec", mock.Anything, specID).Return(&feeds.JobProposalSpec{ ID: specID, }, nil) @@ -189,7 +189,7 @@ func TestResolver_CancelJobProposalSpec(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("CancelSpec", mock.Anything, specID).Return(nil) - f.Mocks.feedsSvc.On("GetSpec", specID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetSpec", mock.Anything, specID).Return(nil, sql.ErrNoRows) }, query: mutation, variables: variables, @@ -245,7 +245,7 @@ func TestResolver_RejectJobProposalSpec(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("RejectSpec", mock.Anything, specID).Return(nil) - f.Mocks.feedsSvc.On("GetSpec", specID).Return(&feeds.JobProposalSpec{ + f.Mocks.feedsSvc.On("GetSpec", mock.Anything, specID).Return(&feeds.JobProposalSpec{ ID: specID, }, nil) }, @@ -276,7 +276,7 @@ func TestResolver_RejectJobProposalSpec(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("RejectSpec", mock.Anything, specID).Return(nil) - f.Mocks.feedsSvc.On("GetSpec", specID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetSpec", mock.Anything, specID).Return(nil, sql.ErrNoRows) }, query: mutation, variables: variables, @@ -335,7 +335,7 @@ func TestResolver_UpdateJobProposalSpecDefinition(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("UpdateSpecDefinition", mock.Anything, specID, "").Return(nil) - f.Mocks.feedsSvc.On("GetSpec", specID).Return(&feeds.JobProposalSpec{ + f.Mocks.feedsSvc.On("GetSpec", mock.Anything, specID).Return(&feeds.JobProposalSpec{ ID: specID, }, nil) }, @@ -367,7 +367,7 @@ func TestResolver_UpdateJobProposalSpecDefinition(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) f.Mocks.feedsSvc.On("UpdateSpecDefinition", mock.Anything, specID, "").Return(nil) - f.Mocks.feedsSvc.On("GetSpec", specID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetSpec", mock.Anything, specID).Return(nil, sql.ErrNoRows) }, query: mutation, variables: variables, @@ -446,7 +446,7 @@ func TestResolver_GetJobProposal_Spec(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.feedsSvc.On("GetJobProposal", jpID).Return(&feeds.JobProposal{ + f.Mocks.feedsSvc.On("GetJobProposal", mock.Anything, jpID).Return(&feeds.JobProposal{ ID: jpID, Status: feeds.JobProposalStatusApproved, FeedsManagerID: 1, @@ -454,7 +454,7 @@ func TestResolver_GetJobProposal_Spec(t *testing.T) { PendingUpdate: false, }, nil) f.Mocks.feedsSvc. - On("ListSpecsByJobProposalIDs", []int64{jpID}). + On("ListSpecsByJobProposalIDs", mock.Anything, []int64{jpID}). Return(specs, nil) f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) }, diff --git a/core/web/resolver/job_proposal_test.go b/core/web/resolver/job_proposal_test.go index 466ddd5d8ab..5544b39c936 100644 --- a/core/web/resolver/job_proposal_test.go +++ b/core/web/resolver/job_proposal_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/google/uuid" + "github.com/stretchr/testify/mock" "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink/v2/core/services/feeds" @@ -64,13 +65,13 @@ func TestResolver_GetJobProposal(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.feedsSvc.On("ListManagersByIDs", []int64{1}).Return([]feeds.FeedsManager{ + f.Mocks.feedsSvc.On("ListManagersByIDs", mock.Anything, []int64{1}).Return([]feeds.FeedsManager{ { ID: 1, Name: "manager", }, }, nil) - f.Mocks.feedsSvc.On("GetJobProposal", jpID).Return(&feeds.JobProposal{ + f.Mocks.feedsSvc.On("GetJobProposal", mock.Anything, jpID).Return(&feeds.JobProposal{ ID: jpID, Name: null.StringFrom(name), Status: feeds.JobProposalStatusApproved, @@ -89,7 +90,7 @@ func TestResolver_GetJobProposal(t *testing.T) { name: "not found error", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.feedsSvc.On("GetJobProposal", jpID).Return(nil, sql.ErrNoRows) + f.Mocks.feedsSvc.On("GetJobProposal", mock.Anything, jpID).Return(nil, sql.ErrNoRows) f.App.On("GetFeedsService").Return(f.Mocks.feedsSvc) }, query: query, diff --git a/core/web/resolver/job_run_test.go b/core/web/resolver/job_run_test.go index a35a2f66ac5..51631864e8c 100644 --- a/core/web/resolver/job_run_test.go +++ b/core/web/resolver/job_run_test.go @@ -40,7 +40,7 @@ func TestQuery_PaginatedJobRuns(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("PipelineRuns", (*int32)(nil), PageDefaultOffset, PageDefaultLimit).Return([]pipeline.Run{ + f.Mocks.jobORM.On("PipelineRuns", mock.Anything, (*int32)(nil), PageDefaultOffset, PageDefaultLimit).Return([]pipeline.Run{ { ID: int64(200), }, @@ -64,7 +64,7 @@ func TestQuery_PaginatedJobRuns(t *testing.T) { name: "generic error on PipelineRuns()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("PipelineRuns", (*int32)(nil), PageDefaultOffset, PageDefaultLimit).Return(nil, 0, gError) + f.Mocks.jobORM.On("PipelineRuns", mock.Anything, (*int32)(nil), PageDefaultOffset, PageDefaultLimit).Return(nil, 0, gError) f.App.On("JobORM").Return(f.Mocks.jobORM) }, query: query, @@ -131,7 +131,7 @@ func TestResolver_JobRun(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindPipelineRunByID", int64(2)).Return(pipeline.Run{ + f.Mocks.jobORM.On("FindPipelineRunByID", mock.Anything, int64(2)).Return(pipeline.Run{ ID: 2, PipelineSpecID: 5, CreatedAt: f.Timestamp(), @@ -142,7 +142,7 @@ func TestResolver_JobRun(t *testing.T) { Outputs: outputs, State: pipeline.RunStatusErrored, }, nil) - f.Mocks.jobORM.On("FindJobsByPipelineSpecIDs", []int32{5}).Return([]job.Job{ + f.Mocks.jobORM.On("FindJobsByPipelineSpecIDs", mock.Anything, []int32{5}).Return([]job.Job{ { ID: 1, PipelineSpecID: 2, @@ -180,7 +180,7 @@ func TestResolver_JobRun(t *testing.T) { name: "not found error", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindPipelineRunByID", int64(2)).Return(pipeline.Run{}, sql.ErrNoRows) + f.Mocks.jobORM.On("FindPipelineRunByID", mock.Anything, int64(2)).Return(pipeline.Run{}, sql.ErrNoRows) f.App.On("JobORM").Return(f.Mocks.jobORM) }, query: query, @@ -197,7 +197,7 @@ func TestResolver_JobRun(t *testing.T) { name: "generic error on FindPipelineRunByID()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindPipelineRunByID", int64(2)).Return(pipeline.Run{}, gError) + f.Mocks.jobORM.On("FindPipelineRunByID", mock.Anything, int64(2)).Return(pipeline.Run{}, gError) f.App.On("JobORM").Return(f.Mocks.jobORM) }, query: query, diff --git a/core/web/resolver/job_test.go b/core/web/resolver/job_test.go index e91e37b6903..0615e47a621 100644 --- a/core/web/resolver/job_test.go +++ b/core/web/resolver/job_test.go @@ -72,7 +72,7 @@ func TestResolver_Jobs(t *testing.T) { plnSpecID := int32(12) f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobs", 0, 50).Return([]job.Job{ + f.Mocks.jobORM.On("FindJobs", mock.Anything, 0, 50).Return([]job.Job{ { ID: 1, Name: null.StringFrom("job1"), @@ -89,13 +89,13 @@ func TestResolver_Jobs(t *testing.T) { }, }, 1, nil) f.Mocks.jobORM. - On("FindPipelineRunIDsByJobID", int32(1), 0, 50). + On("FindPipelineRunIDsByJobID", mock.Anything, int32(1), 0, 50). Return([]int64{200}, nil) f.Mocks.jobORM. - On("FindPipelineRunsByIDs", []int64{200}). + On("FindPipelineRunsByIDs", mock.Anything, []int64{200}). Return([]pipeline.Run{{ID: 200}}, nil) f.Mocks.jobORM. - On("CountPipelineRunsByJobID", int32(1)). + On("CountPipelineRunsByJobID", mock.Anything, int32(1)). Return(int32(1), nil) }, query: query, @@ -208,7 +208,7 @@ func TestResolver_Job(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ ID: 1, Name: null.StringFrom("job1"), SchemaVersion: 1, @@ -223,13 +223,13 @@ func TestResolver_Job(t *testing.T) { }, }, nil) f.Mocks.jobORM. - On("FindPipelineRunIDsByJobID", int32(1), 0, 50). + On("FindPipelineRunIDsByJobID", mock.Anything, int32(1), 0, 50). Return([]int64{200}, nil) f.Mocks.jobORM. - On("FindPipelineRunsByIDs", []int64{200}). + On("FindPipelineRunsByIDs", mock.Anything, []int64{200}). Return([]pipeline.Run{{ID: 200}}, nil) f.Mocks.jobORM. - On("CountPipelineRunsByJobID", int32(1)). + On("CountPipelineRunsByJobID", mock.Anything, int32(1)). Return(int32(1), nil) }, query: query, @@ -240,7 +240,7 @@ func TestResolver_Job(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{}, sql.ErrNoRows) + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{}, sql.ErrNoRows) }, query: query, result: ` @@ -257,7 +257,7 @@ func TestResolver_Job(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ ID: 1, Name: null.StringFrom("job1"), SchemaVersion: 1, @@ -272,13 +272,13 @@ func TestResolver_Job(t *testing.T) { }, }, chains.ErrNoSuchChainID) f.Mocks.jobORM. - On("FindPipelineRunIDsByJobID", int32(1), 0, 50). + On("FindPipelineRunIDsByJobID", mock.Anything, int32(1), 0, 50). Return([]int64{200}, nil) f.Mocks.jobORM. - On("FindPipelineRunsByIDs", []int64{200}). + On("FindPipelineRunsByIDs", mock.Anything, []int64{200}). Return([]pipeline.Run{{ID: 200}}, nil) f.Mocks.jobORM. - On("CountPipelineRunsByJobID", int32(1)). + On("CountPipelineRunsByJobID", mock.Anything, int32(1)). Return(int32(1), nil) }, query: query, @@ -453,7 +453,7 @@ func TestResolver_DeleteJob(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ ID: id, Name: null.StringFrom("test-job"), ExternalJobID: extJID, @@ -471,7 +471,7 @@ func TestResolver_DeleteJob(t *testing.T) { name: "not found on FindJob()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{}, sql.ErrNoRows) + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{}, sql.ErrNoRows) f.App.On("JobORM").Return(f.Mocks.jobORM) }, query: mutation, @@ -489,7 +489,7 @@ func TestResolver_DeleteJob(t *testing.T) { name: "not found on DeleteJob()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{}, nil) + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{}, nil) f.App.On("JobORM").Return(f.Mocks.jobORM) f.App.On("DeleteJob", mock.Anything, id).Return(sql.ErrNoRows) }, @@ -508,7 +508,7 @@ func TestResolver_DeleteJob(t *testing.T) { name: "generic error on FindJob()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{}, gError) + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{}, gError) f.App.On("JobORM").Return(f.Mocks.jobORM) }, query: mutation, @@ -527,7 +527,7 @@ func TestResolver_DeleteJob(t *testing.T) { name: "generic error on DeleteJob()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{}, nil) + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{}, nil) f.App.On("JobORM").Return(f.Mocks.jobORM) f.App.On("DeleteJob", mock.Anything, id).Return(gError) }, diff --git a/core/web/resolver/mutation.go b/core/web/resolver/mutation.go index 9663f9dfe82..641eabdfd8b 100644 --- a/core/web/resolver/mutation.go +++ b/core/web/resolver/mutation.go @@ -238,7 +238,7 @@ func (r *Resolver) CreateFeedsManagerChainConfig(ctx context.Context, args struc return nil, err } - ccfg, err := fsvc.GetChainConfig(id) + ccfg, err := fsvc.GetChainConfig(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewCreateFeedsManagerChainConfigPayload(nil, err, nil), nil @@ -267,7 +267,7 @@ func (r *Resolver) DeleteFeedsManagerChainConfig(ctx context.Context, args struc fsvc := r.App.GetFeedsService() - ccfg, err := fsvc.GetChainConfig(id) + ccfg, err := fsvc.GetChainConfig(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewDeleteFeedsManagerChainConfigPayload(nil, err), nil @@ -367,7 +367,7 @@ func (r *Resolver) UpdateFeedsManagerChainConfig(ctx context.Context, args struc return nil, err } - ccfg, err := fsvc.GetChainConfig(id) + ccfg, err := fsvc.GetChainConfig(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewUpdateFeedsManagerChainConfigPayload(nil, err, nil), nil @@ -418,7 +418,7 @@ func (r *Resolver) CreateFeedsManager(ctx context.Context, args struct { return nil, err } - mgr, err := feedsService.GetManager(id) + mgr, err := feedsService.GetManager(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewCreateFeedsManagerPayload(nil, err, nil), nil @@ -541,7 +541,7 @@ func (r *Resolver) UpdateFeedsManager(ctx context.Context, args struct { return nil, err } - mgr, err = feedsService.GetManager(id) + mgr, err = feedsService.GetManager(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewUpdateFeedsManagerPayload(nil, err, nil), nil @@ -615,7 +615,7 @@ func (r *Resolver) DeleteBridge(ctx context.Context, args struct { return nil, err } - jobsUsingBridge, err := r.App.JobORM().FindJobIDsWithBridge(string(args.ID)) + jobsUsingBridge, err := r.App.JobORM().FindJobIDsWithBridge(ctx, string(args.ID)) if err != nil { return nil, err } @@ -751,7 +751,7 @@ func (r *Resolver) ApproveJobProposalSpec(ctx context.Context, args struct { return nil, err } - spec, err := feedsSvc.GetSpec(id) + spec, err := feedsSvc.GetSpec(ctx, id) if err != nil { if !errors.Is(err, sql.ErrNoRows) { return nil, err @@ -786,7 +786,7 @@ func (r *Resolver) CancelJobProposalSpec(ctx context.Context, args struct { return nil, err } - spec, err := feedsSvc.GetSpec(id) + spec, err := feedsSvc.GetSpec(ctx, id) if err != nil { if !errors.Is(err, sql.ErrNoRows) { return nil, err @@ -821,7 +821,7 @@ func (r *Resolver) RejectJobProposalSpec(ctx context.Context, args struct { return nil, err } - spec, err := feedsSvc.GetSpec(id) + spec, err := feedsSvc.GetSpec(ctx, id) if err != nil { if !errors.Is(err, sql.ErrNoRows) { return nil, err @@ -859,7 +859,7 @@ func (r *Resolver) UpdateJobProposalSpecDefinition(ctx context.Context, args str return nil, err } - spec, err := feedsSvc.GetSpec(id) + spec, err := feedsSvc.GetSpec(ctx, id) if err != nil { if !errors.Is(err, sql.ErrNoRows) { return nil, err @@ -1039,7 +1039,7 @@ func (r *Resolver) CreateJob(ctx context.Context, args struct { case job.VRF: jb, err = vrfcommon.ValidatedVRFSpec(args.Input.TOML) case job.Webhook: - jb, err = webhook.ValidatedWebhookSpec(args.Input.TOML, r.App.GetExternalInitiatorManager()) + jb, err = webhook.ValidatedWebhookSpec(ctx, args.Input.TOML, r.App.GetExternalInitiatorManager()) case job.BlockhashStore: jb, err = blockhashstore.ValidatedSpec(args.Input.TOML) case job.BlockHeaderFeeder: @@ -1085,7 +1085,7 @@ func (r *Resolver) DeleteJob(ctx context.Context, args struct { return nil, err } - j, err := r.App.JobORM().FindJobWithoutSpecErrors(id) + j, err := r.App.JobORM().FindJobWithoutSpecErrors(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewDeleteJobPayload(r.App, nil, err), nil @@ -1119,7 +1119,7 @@ func (r *Resolver) DismissJobError(ctx context.Context, args struct { return nil, err } - specErr, err := r.App.JobORM().FindSpecError(id) + specErr, err := r.App.JobORM().FindSpecError(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewDismissJobErrorPayload(nil, err), nil diff --git a/core/web/resolver/query.go b/core/web/resolver/query.go index e24974e765d..9de678adc51 100644 --- a/core/web/resolver/query.go +++ b/core/web/resolver/query.go @@ -132,7 +132,7 @@ func (r *Resolver) FeedsManager(ctx context.Context, args struct{ ID graphql.ID return nil, err } - mgr, err := r.App.GetFeedsService().GetManager(id) + mgr, err := r.App.GetFeedsService().GetManager(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewFeedsManagerPayload(nil, err), nil @@ -149,7 +149,7 @@ func (r *Resolver) FeedsManagers(ctx context.Context) (*FeedsManagersPayloadReso return nil, err } - mgrs, err := r.App.GetFeedsService().ListManagers() + mgrs, err := r.App.GetFeedsService().ListManagers(ctx) if err != nil { return nil, err } @@ -168,7 +168,7 @@ func (r *Resolver) Job(ctx context.Context, args struct{ ID graphql.ID }) (*JobP return nil, err } - j, err := r.App.JobORM().FindJobWithoutSpecErrors(id) + j, err := r.App.JobORM().FindJobWithoutSpecErrors(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewJobPayload(r.App, nil, err), nil @@ -197,7 +197,7 @@ func (r *Resolver) Jobs(ctx context.Context, args struct { offset := pageOffset(args.Offset) limit := pageLimit(args.Limit) - jobs, count, err := r.App.JobORM().FindJobs(offset, limit) + jobs, count, err := r.App.JobORM().FindJobs(ctx, offset, limit) if err != nil { return nil, err } @@ -328,7 +328,7 @@ func (r *Resolver) JobProposal(ctx context.Context, args struct { return nil, err } - jp, err := r.App.GetFeedsService().GetJobProposal(id) + jp, err := r.App.GetFeedsService().GetJobProposal(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewJobProposalPayload(nil, err), nil @@ -377,7 +377,7 @@ func (r *Resolver) JobRuns(ctx context.Context, args struct { limit := pageLimit(args.Limit) offset := pageOffset(args.Offset) - runs, count, err := r.App.JobORM().PipelineRuns(nil, offset, limit) + runs, count, err := r.App.JobORM().PipelineRuns(ctx, nil, offset, limit) if err != nil { return nil, err } @@ -397,7 +397,7 @@ func (r *Resolver) JobRun(ctx context.Context, args struct { return nil, err } - jr, err := r.App.JobORM().FindPipelineRunByID(id) + jr, err := r.App.JobORM().FindPipelineRunByID(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return NewJobRunPayload(nil, r.App, err), nil diff --git a/core/web/resolver/spec_test.go b/core/web/resolver/spec_test.go index 7021576fdcf..43682c14ead 100644 --- a/core/web/resolver/spec_test.go +++ b/core/web/resolver/spec_test.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/lib/pq" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "gopkg.in/guregu/null.v4" @@ -35,7 +36,7 @@ func TestResolver_CronSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.Cron, CronSpec: &job.CronSpec{ CronSchedule: "CRON_TZ=UTC 0 0 1 1 *", @@ -89,7 +90,7 @@ func TestResolver_DirectRequestSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.DirectRequest, DirectRequestSpec: &job.DirectRequestSpec{ ContractAddress: contractAddress, @@ -154,7 +155,7 @@ func TestResolver_FluxMonitorSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.FluxMonitor, FluxMonitorSpec: &job.FluxMonitorSpec{ ContractAddress: contractAddress, @@ -221,7 +222,7 @@ func TestResolver_FluxMonitorSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.FluxMonitor, FluxMonitorSpec: &job.FluxMonitorSpec{ ContractAddress: contractAddress, @@ -304,7 +305,7 @@ func TestResolver_KeeperSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.Keeper, KeeperSpec: &job.KeeperSpec{ ContractAddress: contractAddress, @@ -368,7 +369,7 @@ func TestResolver_OCRSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.OffchainReporting, OCROracleSpec: &job.OCROracleSpec{ BlockchainTimeout: models.Interval(1 * time.Minute), @@ -473,7 +474,7 @@ func TestResolver_OCR2Spec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.OffchainReporting2, OCR2OracleSpec: &job.OCR2OracleSpec{ BlockchainTimeout: models.Interval(1 * time.Minute), @@ -575,7 +576,7 @@ func TestResolver_VRFSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.VRF, VRFSpec: &job.VRFSpec{ BatchCoordinatorAddress: &batchCoordinatorAddress, @@ -671,7 +672,7 @@ func TestResolver_WebhookSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.Webhook, WebhookSpec: &job.WebhookSpec{ CreatedAt: f.Timestamp(), @@ -740,7 +741,7 @@ func TestResolver_BlockhashStoreSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.BlockhashStore, BlockhashStoreSpec: &job.BlockhashStoreSpec{ CoordinatorV1Address: &coordinatorV1Address, @@ -844,7 +845,7 @@ func TestResolver_BlockHeaderFeederSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.BlockHeaderFeeder, BlockHeaderFeederSpec: &job.BlockHeaderFeederSpec{ CoordinatorV1Address: &coordinatorV1Address, @@ -931,7 +932,7 @@ func TestResolver_BootstrapSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.Bootstrap, BootstrapSpec: &job.BootstrapSpec{ ID: id, @@ -1003,7 +1004,7 @@ func TestResolver_WorkflowSpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.Workflow, WorkflowSpec: &job.WorkflowSpec{ ID: id, @@ -1061,7 +1062,7 @@ func TestResolver_GatewaySpec(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", id).Return(job.Job{ + f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id).Return(job.Job{ Type: job.Gateway, GatewaySpec: &job.GatewaySpec{ ID: id, diff --git a/core/web/sessions_controller_test.go b/core/web/sessions_controller_test.go index cd63628390e..049be4e2b69 100644 --- a/core/web/sessions_controller_test.go +++ b/core/web/sessions_controller_test.go @@ -8,10 +8,10 @@ import ( "testing" "time" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" clhttptest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/httptest" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/sessions" "github.com/smartcontractkit/chainlink/v2/core/web" @@ -25,7 +25,7 @@ func TestSessionsController_Create(t *testing.T) { ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) user := cltest.MustRandomUser(t) require.NoError(t, app.AuthenticationProvider().CreateUser(ctx, &user)) @@ -44,6 +44,7 @@ func TestSessionsController_Create(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { + ctx := testutils.Context(t) body := fmt.Sprintf(`{"email":"%s","password":"%s"}`, test.email, test.password) request, err := http.NewRequestWithContext(ctx, "POST", app.Server.URL+"/sessions", bytes.NewBufferString(body)) assert.NoError(t, err) @@ -78,9 +79,10 @@ func TestSessionsController_Create(t *testing.T) { } } -func mustInsertSession(t *testing.T, q pg.Q, session *sessions.Session) { +func mustInsertSession(t *testing.T, ds sqlutil.DataSource, session *sessions.Session) { + ctx := testutils.Context(t) sql := "INSERT INTO sessions (id, email, last_used, created_at) VALUES ($1, $2, $3, $4) RETURNING *" - _, err := q.Exec(sql, session.ID, session.Email, session.LastUsed, session.CreatedAt) + _, err := ds.ExecContext(ctx, sql, session.ID, session.Email, session.LastUsed, session.CreatedAt) require.NoError(t, err) } @@ -97,8 +99,7 @@ func TestSessionsController_Create_ReapSessions(t *testing.T) { staleSession := cltest.NewSession() staleSession.LastUsed = time.Now().Add(-cltest.MustParseDuration(t, "241h")) staleSession.Email = user.Email - q := pg.NewQ(app.GetSqlxDB(), app.GetLogger(), app.GetConfig().Database()) - mustInsertSession(t, q, &staleSession) + mustInsertSession(t, app.GetDB(), &staleSession) body := fmt.Sprintf(`{"email":"%s","password":"%s"}`, user.Email, cltest.Password) req, err := http.NewRequestWithContext(ctx, "POST", app.Server.URL+"/sessions", bytes.NewBufferString(body)) @@ -127,15 +128,14 @@ func TestSessionsController_Destroy(t *testing.T) { ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) user := cltest.MustRandomUser(t) require.NoError(t, app.AuthenticationProvider().CreateUser(ctx, &user)) correctSession := sessions.NewSession() correctSession.Email = user.Email - q := pg.NewQ(app.GetSqlxDB(), app.GetLogger(), app.GetConfig().Database()) - mustInsertSession(t, q, &correctSession) + mustInsertSession(t, app.GetDB(), &correctSession) client := clhttptest.NewTestLocalOnlyHTTPClient() tests := []struct { @@ -148,6 +148,7 @@ func TestSessionsController_Destroy(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { + ctx := testutils.Context(t) cookie := cltest.MustGenerateSessionCookie(t, test.sessionID) request, err := http.NewRequestWithContext(ctx, "DELETE", app.Server.URL+"/sessions", nil) assert.NoError(t, err) @@ -173,8 +174,7 @@ func TestSessionsController_Destroy_ReapSessions(t *testing.T) { client := clhttptest.NewTestLocalOnlyHTTPClient() app := cltest.NewApplicationEVMDisabled(t) - q := pg.NewQ(app.GetSqlxDB(), app.GetLogger(), app.GetConfig().Database()) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) user := cltest.MustRandomUser(t) require.NoError(t, app.AuthenticationProvider().CreateUser(ctx, &user)) @@ -182,13 +182,13 @@ func TestSessionsController_Destroy_ReapSessions(t *testing.T) { correctSession := sessions.NewSession() correctSession.Email = user.Email - mustInsertSession(t, q, &correctSession) + mustInsertSession(t, app.GetDB(), &correctSession) cookie := cltest.MustGenerateSessionCookie(t, correctSession.ID) staleSession := cltest.NewSession() staleSession.Email = user.Email staleSession.LastUsed = time.Now().Add(-cltest.MustParseDuration(t, "241h")) - mustInsertSession(t, q, &staleSession) + mustInsertSession(t, app.GetDB(), &staleSession) request, err := http.NewRequestWithContext(ctx, "DELETE", app.Server.URL+"/sessions", nil) assert.NoError(t, err) diff --git a/go.mod b/go.mod index b357e57eac5..0a09e3d9693 100644 --- a/go.mod +++ b/go.mod @@ -73,7 +73,7 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.10 github.com/smartcontractkit/chainlink-automation v1.0.3 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 + github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba58 diff --git a/go.sum b/go.sum index 664ddd5efe0..68cd0abbd7f 100644 --- a/go.sum +++ b/go.sum @@ -1182,8 +1182,8 @@ github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfs github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 h1:54hM3/SrOM166it2K35hGb5K7gQ49/Op0aHp9WkqpqU= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 h1:MvaNzuaQh1vX4CAYLM8qFd99cf0ZF1JNwtDZtLU7WvU= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee h1:eFuBKyEbL2b+eyfgV/Eu9+8HuCEev+IcBi+K9l1dG7g= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab h1:Ct1oUlyn03HDUVdFHJqtRGRUujMqdoMzvf/Cjhe30Ag= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index d07e68c9f7a..24a5d1ee7a6 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -377,7 +377,7 @@ require ( github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 // indirect + github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba58 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index efef8224d85..8c66ce7ca8c 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1519,8 +1519,8 @@ github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfs github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 h1:54hM3/SrOM166it2K35hGb5K7gQ49/Op0aHp9WkqpqU= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 h1:MvaNzuaQh1vX4CAYLM8qFd99cf0ZF1JNwtDZtLU7WvU= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee h1:eFuBKyEbL2b+eyfgV/Eu9+8HuCEev+IcBi+K9l1dG7g= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab h1:Ct1oUlyn03HDUVdFHJqtRGRUujMqdoMzvf/Cjhe30Ag= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index a7a37ab1e0e..13a8e2f4f34 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -366,7 +366,7 @@ require ( github.com/shopspring/decimal v1.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 // indirect + github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba58 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index d50656bfed5..5720d19de02 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1502,8 +1502,8 @@ github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfs github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 h1:54hM3/SrOM166it2K35hGb5K7gQ49/Op0aHp9WkqpqU= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 h1:MvaNzuaQh1vX4CAYLM8qFd99cf0ZF1JNwtDZtLU7WvU= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee h1:eFuBKyEbL2b+eyfgV/Eu9+8HuCEev+IcBi+K9l1dG7g= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab h1:Ct1oUlyn03HDUVdFHJqtRGRUujMqdoMzvf/Cjhe30Ag= From 74c6d028659e80d9b5092c2406a598a1d2249d21 Mon Sep 17 00:00:00 2001 From: Chris Cushman <104409744+vreff@users.noreply.github.com> Date: Wed, 24 Apr 2024 18:32:21 -0400 Subject: [PATCH 07/34] Revert ocr2vrf gethwrappers change (#12957) * Revert "[VRF-886] Move vestigial ocr2vrf gethwrappers to chainlink-vrf archive (#12134)" This reverts commit e9ea7c85facefb9bcbc0f9baf9e9f4848fda938e. * fix conflicts --- contracts/GNUmakefile | 12 + .../scripts/native_solc_compile_all_ocr2vrf | 42 + .../gethwrappers/ocr2vrf/generated/dkg/dkg.go | 1274 ++++++ .../load_test_beacon_consumer.go | 1422 ++++++ .../generated/vrf_beacon/vrf_beacon.go | 2846 ++++++++++++ .../vrf_beacon_consumer.go | 1034 +++++ .../vrf_coordinator/vrf_coordinator.go | 3870 +++++++++++++++++ ...rapper-dependency-versions-do-not-edit.txt | 7 + core/gethwrappers/ocr2vrf/go_generate.go | 10 + core/internal/mocks/go_generate.go | 4 +- core/scripts/ocr2vrf/util.go | 10 +- core/scripts/ocr2vrf/verify.go | 6 +- .../ocr2vrf/coordinator/coordinator.go | 8 +- .../ocr2vrf/coordinator/coordinator_test.go | 6 +- .../ocr2vrf/coordinator/mocks/vrf_beacon.go | 2 +- .../coordinator/mocks/vrf_coordinator.go | 2 +- .../plugins/ocr2vrf/coordinator/router.go | 4 +- .../ocr2vrf/coordinator/router_test.go | 4 +- .../plugins/ocr2vrf/coordinator/topics.go | 4 +- .../internal/ocr2vrf_integration_test.go | 10 +- go.mod | 2 +- go.sum | 4 +- .../contracts/contract_vrf_models.go | 4 +- .../contracts/ethereum_ocr2vrf_contracts.go | 8 +- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 +- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 +- 28 files changed, 10562 insertions(+), 45 deletions(-) create mode 100755 contracts/scripts/native_solc_compile_all_ocr2vrf create mode 100644 core/gethwrappers/ocr2vrf/generated/dkg/dkg.go create mode 100644 core/gethwrappers/ocr2vrf/generated/load_test_beacon_consumer/load_test_beacon_consumer.go create mode 100644 core/gethwrappers/ocr2vrf/generated/vrf_beacon/vrf_beacon.go create mode 100644 core/gethwrappers/ocr2vrf/generated/vrf_beacon_consumer/vrf_beacon_consumer.go create mode 100644 core/gethwrappers/ocr2vrf/generated/vrf_coordinator/vrf_coordinator.go create mode 100644 core/gethwrappers/ocr2vrf/generation/generated-wrapper-dependency-versions-do-not-edit.txt create mode 100644 core/gethwrappers/ocr2vrf/go_generate.go diff --git a/contracts/GNUmakefile b/contracts/GNUmakefile index 38547ce3a57..4ec8057b975 100644 --- a/contracts/GNUmakefile +++ b/contracts/GNUmakefile @@ -73,6 +73,18 @@ wrappers-all: pnpmdep mockery abigen ## Recompiles solidity contracts and their # go_generate contains a call to compile all contracts before generating wrappers go generate ../core/gethwrappers/go_generate.go +# Custom wrapper generation for OCR2VRF as their contracts do not exist in this repo +.PHONY: go-solidity-wrappers-ocr2vrf +go-solidity-wrappers-ocr2vrf: pnpmdep abigen ## Recompiles OCR2VRF solidity contracts and their go wrappers. + ./scripts/native_solc_compile_all_ocr2vrf + # replace the go:generate_disabled directive with the regular go:generate directive + sed -i '' 's/go:generate_disabled/go:generate/g' ../core/gethwrappers/ocr2vrf/go_generate.go + go generate ../core/gethwrappers/ocr2vrf + go generate ../core/internal/mocks + # put the go:generate_disabled directive back + sed -i '' 's/go:generate/go:generate_disabled/g' ../core/gethwrappers/ocr2vrf/go_generate.go + + help: @echo "" @echo " .__ .__ .__ .__ __" diff --git a/contracts/scripts/native_solc_compile_all_ocr2vrf b/contracts/scripts/native_solc_compile_all_ocr2vrf new file mode 100755 index 00000000000..755edd34f56 --- /dev/null +++ b/contracts/scripts/native_solc_compile_all_ocr2vrf @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +set -e + +echo " ┌──────────────────────────────────────────────┐" +echo " │ Compiling OCR2 VRF contracts... │" +echo " └──────────────────────────────────────────────┘" + +SOLC_VERSION="0.8.19" +OPTIMIZE_RUNS=1000000 +# The VRF contracts are not contained in the `chainlink` repository. +# Change me. +FOLDER="ocr2vrf-origin" + +echo "Compiling OCR2VRF contracts..." + +SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" +ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1; cd ../../ && pwd -P )" +python3 -m pip install --require-hashes -r "$SCRIPTPATH"/requirements.txt + +solc-select install $SOLC_VERSION +solc-select use $SOLC_VERSION +export SOLC_VERSION=$SOLC_VERSION + + +compileContract () { + local contract + contract=$(basename "$1" ".sol") + + solc --overwrite --optimize --optimize-runs "$2" --metadata-hash none \ + -o "$ROOT"/contracts/solc/v0.8.19/"$contract" \ + --abi --bin \ + --allow-paths "$ROOT"/../$FOLDER/contracts \ + "$ROOT"/"$1" +} + +# OCR2VRF +compileContract ../$FOLDER/contracts/DKG.sol $OPTIMIZE_RUNS +compileContract ../$FOLDER/contracts/VRFBeacon.sol $OPTIMIZE_RUNS +compileContract ../$FOLDER/contracts/VRFCoordinator.sol 1 +compileContract ../$FOLDER/contracts/test/TestBeaconVRFConsumer.sol $OPTIMIZE_RUNS +compileContract ../$FOLDER/contracts/test/LoadTestBeaconVRFConsumer.sol $OPTIMIZE_RUNS diff --git a/core/gethwrappers/ocr2vrf/generated/dkg/dkg.go b/core/gethwrappers/ocr2vrf/generated/dkg/dkg.go new file mode 100644 index 00000000000..7a18b7f55bd --- /dev/null +++ b/core/gethwrappers/ocr2vrf/generated/dkg/dkg.go @@ -0,0 +1,1274 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package dkg + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +type KeyDataStructKeyData struct { + PublicKey []byte + Hashes [][32]byte +} + +var DKGMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expectedLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualLength\",\"type\":\"uint256\"}],\"name\":\"CalldataLengthMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expectedNumSignatures\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"rsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"ssLength\",\"type\":\"uint256\"}],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expectedLength\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"actualLength\",\"type\":\"uint256\"}],\"name\":\"InvalidOnchainConfigLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"KeyIDCopyFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"numFaultyOracles\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"}],\"name\":\"NumberOfFaultyOraclesTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"repeatedSignerAddress\",\"type\":\"address\"}],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"repeatedTransmitterAddress\",\"type\":\"address\"}],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numTransmitters\",\"type\":\"uint256\"}],\"name\":\"SignersTransmittersMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"maxOracles\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"providedOracles\",\"type\":\"uint256\"}],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contractDKGClient\",\"name\":\"client\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"errorData\",\"type\":\"bytes\"}],\"name\":\"DKGClientError\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"keyID\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashes\",\"type\":\"bytes32[]\"}],\"indexed\":false,\"internalType\":\"structKeyDataStruct.KeyData\",\"name\":\"key\",\"type\":\"tuple\"}],\"name\":\"KeyGenerated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"keyID\",\"type\":\"bytes32\"},{\"internalType\":\"contractDKGClient\",\"name\":\"clientAddress\",\"type\":\"address\"}],\"name\":\"addClient\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_keyID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_configDigest\",\"type\":\"bytes32\"}],\"name\":\"getKey\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashes\",\"type\":\"bytes32[]\"}],\"internalType\":\"structKeyDataStruct.KeyData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"keyID\",\"type\":\"bytes32\"},{\"internalType\":\"contractDKGClient\",\"name\":\"clientAddress\",\"type\":\"address\"}],\"name\":\"removeClient\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"_f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"_onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"_offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"_offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x60806040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a5565b50505062000150565b336001600160a01b03821603620000ff5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b612b8080620001606000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80638da5cb5b11610081578063c3105a6b1161005b578063c3105a6b146101db578063e3d0e712146101fb578063f2fde38b1461020e57600080fd5b80638da5cb5b14610176578063afcb95d71461019e578063b1dc65a4146101c857600080fd5b806379ba5097116100b257806379ba50971461012b5780637bf1ffc51461013357806381ff70481461014657600080fd5b8063181f5a77146100ce5780635429a79e14610116575b600080fd5b604080518082018252600981527f444b4720302e302e3100000000000000000000000000000000000000000000006020820152905161010d9190611fc8565b60405180910390f35b610129610124366004612004565b610221565b005b6101296104b0565b610129610141366004612004565b6105b2565b6007546005546040805163ffffffff8085168252640100000000909404909316602084015282015260600161010d565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010d565b6005546004546040805160008152602081019390935263ffffffff9091169082015260600161010d565b6101296101d6366004612080565b61061e565b6101ee6101e9366004612165565b610761565b60405161010d9190612187565b6101296102093660046123dd565b61088a565b61012961021c3660046124aa565b6111ec565b610229611200565b60008281526002602090815260408083208054825181850281018501909352808352919290919083018282801561029657602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161026b575b505050505090506000815167ffffffffffffffff8111156102b9576102b961220d565b6040519080825280602002602001820160405280156102e2578160200160208202803683370190505b5090506000805b83518110156103b9578473ffffffffffffffffffffffffffffffffffffffff1684828151811061031b5761031b6124c7565b602002602001015173ffffffffffffffffffffffffffffffffffffffff161461039957848361034a8484612525565b8151811061035a5761035a6124c7565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506103a7565b816103a381612538565b9250505b806103b181612538565b9150506102e9565b5060008184516103c99190612525565b67ffffffffffffffff8111156103e1576103e161220d565b60405190808252806020026020018201604052801561040a578160200160208202803683370190505b50905060005b82855161041d9190612525565b81101561048757838181518110610436576104366124c7565b6020026020010151828281518110610450576104506124c7565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101528061047f81612538565b915050610410565b50600086815260026020908152604090912082516104a792840190611e61565b50505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610536576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6105ba611200565b600091825260026020908152604083208054600181018255908452922090910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055565b60005a604080516020601f8b018190048102820181019092528981529192508a3591818c01359161066e9184918491908e908e908190840183828082843760009201919091525061128392505050565b6040805183815263ffffffff600884901c1660208201527fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a16040805160608101825260055480825260065460ff808216602085015261010090910416928201929092529083146107215780516040517f93df584c00000000000000000000000000000000000000000000000000000000815260048101919091526024810184905260440161052d565b61072f8b8b8b8b8b8b611512565b6107408c8c8c8c8c8c8c8c89611599565b50505063ffffffff811061075657610756612570565b505050505050505050565b604080518082019091526060808252602082015260008381526003602090815260408083208584529091529081902081518083019092528054829082906107a79061259f565b80601f01602080910402602001604051908101604052809291908181526020018280546107d39061259f565b80156108205780601f106107f557610100808354040283529160200191610820565b820191906000526020600020905b81548152906001019060200180831161080357829003601f168201915b505050505081526020016001820180548060200260200160405190810160405280929190818152602001828054801561087857602002820191906000526020600020905b815481526020019060010190808311610864575b50505050508152505090505b92915050565b8551855185601f8311156108d4576040517f809fc428000000000000000000000000000000000000000000000000000000008152601f60048201526024810184905260440161052d565b818314610917576040517f988a0804000000000000000000000000000000000000000000000000000000008152600481018490526024810183905260440161052d565b6109228160036125f2565b60ff168311610969576040517ffda9db7800000000000000000000000000000000000000000000000000000000815260ff821660048201526024810184905260440161052d565b8060ff166000036109a6576040517fe77dba5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109ae611200565b6040805160c0810182528a8152602081018a905260ff8916918101919091526060810187905267ffffffffffffffff8616608082015260a081018590525b60095415610ba157600954600090610a0690600190612525565b9050600060098281548110610a1d57610a1d6124c7565b6000918252602082200154600a805473ffffffffffffffffffffffffffffffffffffffff90921693509084908110610a5757610a576124c7565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff85811684526008909252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090811690915592909116808452922080549091169055600980549192509080610ad757610ad7612615565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055019055600a805480610b4057610b40612615565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055019055506109ec915050565b60005b81515181101561101c5760006008600084600001518481518110610bca57610bca6124c7565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115610c1457610c14612644565b14610c84578151805182908110610c2d57610c2d6124c7565b60200260200101516040517f7451f83e00000000000000000000000000000000000000000000000000000000815260040161052d919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b6040805180820190915260ff82168152600160208201528251805160089160009185908110610cb557610cb56124c7565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115610d5657610d56612644565b021790555060009150610d669050565b6008600084602001518481518110610d8057610d806124c7565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115610dca57610dca612644565b14610e3c5781602001518181518110610de557610de56124c7565b60200260200101516040517fe8d2989900000000000000000000000000000000000000000000000000000000815260040161052d919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b6040805180820190915260ff821681526020810160028152506008600084602001518481518110610e6f57610e6f6124c7565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115610f1057610f10612644565b021790555050825180516009925083908110610f2e57610f2e6124c7565b602090810291909101810151825460018101845560009384529282902090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092179091558201518051600a919083908110610faa57610faa6124c7565b60209081029190910181015182546001810184556000938452919092200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790558061101481612538565b915050610ba4565b506040810151600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055600754640100000000900463ffffffff1661106c611a2f565b6007805463ffffffff928316640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff8216811783556001936000926110bd928692908116911617612673565b92506101000a81548163ffffffff021916908363ffffffff160217905550600061111e4630600760009054906101000a900463ffffffff1663ffffffff1686600001518760200151886040015189606001518a608001518b60a00151611ac6565b6005819055835180516006805460ff909216610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff9092169190911790556007546020860151604080880151606089015160808a015160a08b015193519798507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05976111c3978b978b9763ffffffff9091169691959094909390929091906126e1565b60405180910390a16111de8360400151846060015183611b71565b505050505050505050505050565b6111f4611200565b6111fd81611d6c565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611281576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161052d565b565b60006060808380602001905181019061129c9190612777565b60408051808201825283815260208082018490526000868152600282528381208054855181850281018501909652808652979a509598509396509094929391929083018282801561132357602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116112f8575b5050505050905060005b815181101561144d57818181518110611348576113486124c7565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1663bf2732c7846040518263ffffffff1660e01b81526004016113889190612187565b600060405180830381600087803b1580156113a257600080fd5b505af19250505080156113b3575060015b61143b573d8080156113e1576040519150601f19603f3d011682016040523d82523d6000602084013e6113e6565b606091505b507f116391732f5df106193bda7cedf1728f3b07b62f6cdcdd611c9eeec44efcae5483838151811061141a5761141a6124c7565b602002602001015182604051611431929190612875565b60405180910390a1505b8061144581612538565b91505061132d565b5060008581526003602090815260408083208b845290915290208251839190819061147890826128fb565b5060208281015180516114919260018501920190611eeb565b5090505084887fc8db841f5b2231ccf7190311f440aa197b161e369f3b40b023508160cc555656846040516114c69190612187565b60405180910390a350506004805460089690961c63ffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000909616959095179094555050505050565b600061151f826020612a15565b61152a856020612a15565b61153688610144612a2c565b6115409190612a2c565b61154a9190612a2c565b611555906000612a2c565b90503681146104a7576040517ff7b94f0a0000000000000000000000000000000000000000000000000000000081526004810182905236602482015260440161052d565b60006002826020015183604001516115b19190612a3f565b6115bb9190612a58565b6115c6906001612a3f565b60408051600180825281830190925260ff929092169250600091906020820181803683370190505090508160f81b81600081518110611607576116076124c7565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535086821415806116455750868514155b1561168d576040517fe307bd5700000000000000000000000000000000000000000000000000000000815260048101839052602481018890526044810186905260640161052d565b3360009081526008602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156116d0576116d0612644565b60028111156116e1576116e1612644565b90525090506002816020015160028111156116fe576116fe612644565b1415806117465750600a816000015160ff1681548110611720576117206124c7565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff163314155b1561177f576040517f2d0f0c0f00000000000000000000000000000000000000000000000000000000815233600482015260240161052d565b50505060008888604051611794929190612aa1565b6040519081900381206117ab918c90602001612ab1565b6040516020818303038152906040528051906020012090506117cb611f26565b604080518082019091526000808252602082015260005b88811015611a20576000600185888460208110611801576118016124c7565b61180e91901a601b612a3f565b8d8d86818110611820576118206124c7565b905060200201358c8c87818110611839576118396124c7565b9050602002013560405160008152602001604052604051611876949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611898573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526008602090815290849020838501909452835460ff8082168552929650929450840191610100900416600281111561191857611918612644565b600281111561192957611929612644565b905250925060018360200151600281111561194657611946612644565b14611995576040517fbf18af4300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161052d565b8251849060ff16601f81106119ac576119ac6124c7565b6020020151156119e8576040517f21cf3b4400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184846000015160ff16601f8110611a0357611a036124c7565b911515602090920201525080611a1881612538565b9150506117e2565b50505050505050505050505050565b60004661a4b1811480611a44575062066eed81145b15611abf57606473ffffffffffffffffffffffffffffffffffffffff1663a3b1b31d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ab99190612ac5565b91505090565b4391505090565b6000808a8a8a8a8a8a8a8a8a604051602001611aea99989796959493929190612ade565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b6000808351602014611bbc5783516040517f1625adfe00000000000000000000000000000000000000000000000000000000815260206004820152602481019190915260440161052d565b60208401519150808203611bfc576040517faf5e77d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201909152606080825260208201526000838152600360209081526040808320878452909152902081518291908190611c3a90826128fb565b506020828101518051611c539260018501920190611eeb565b505050600083815260026020908152604080832080548251818502810185019093528083529192909190830182828015611cc357602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311611c98575b5050505050905060005b8151811015611d6257818181518110611ce857611ce86124c7565b602002602001015173ffffffffffffffffffffffffffffffffffffffff166355e487496040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611d3757600080fd5b505af1158015611d4b573d6000803e3d6000fd5b505050508080611d5a90612538565b915050611ccd565b5050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603611deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161052d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b828054828255906000526020600020908101928215611edb579160200282015b82811115611edb57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190611e81565b50611ee7929150611f45565b5090565b828054828255906000526020600020908101928215611edb579160200282015b82811115611edb578251825591602001919060010190611f0b565b604051806103e00160405280601f906020820280368337509192915050565b5b80821115611ee75760008155600101611f46565b60005b83811015611f75578181015183820152602001611f5d565b50506000910152565b60008151808452611f96816020860160208601611f5a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611fdb6020830184611f7e565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146111fd57600080fd5b6000806040838503121561201757600080fd5b82359150602083013561202981611fe2565b809150509250929050565b60008083601f84011261204657600080fd5b50813567ffffffffffffffff81111561205e57600080fd5b6020830191508360208260051b850101111561207957600080fd5b9250929050565b60008060008060008060008060e0898b03121561209c57600080fd5b606089018a8111156120ad57600080fd5b8998503567ffffffffffffffff808211156120c757600080fd5b818b0191508b601f8301126120db57600080fd5b8135818111156120ea57600080fd5b8c60208285010111156120fc57600080fd5b6020830199508098505060808b013591508082111561211a57600080fd5b6121268c838d01612034565b909750955060a08b013591508082111561213f57600080fd5b5061214c8b828c01612034565b999c989b50969995989497949560c00135949350505050565b6000806040838503121561217857600080fd5b50508035926020909101359150565b6000602080835283516040828501526121a36060850182611f7e565b858301518582037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0016040870152805180835290840192506000918401905b8083101561220257835182529284019260019290920191908401906121e2565b509695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156122835761228361220d565b604052919050565b600067ffffffffffffffff8211156122a5576122a561220d565b5060051b60200190565b600082601f8301126122c057600080fd5b813560206122d56122d08361228b565b61223c565b82815260059290921b840181019181810190868411156122f457600080fd5b8286015b8481101561220257803561230b81611fe2565b83529183019183016122f8565b803560ff8116811461232957600080fd5b919050565b600067ffffffffffffffff8211156123485761234861220d565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261238557600080fd5b81356123936122d08261232e565b8181528460208386010111156123a857600080fd5b816020850160208301376000918101602001919091529392505050565b803567ffffffffffffffff8116811461232957600080fd5b60008060008060008060c087890312156123f657600080fd5b863567ffffffffffffffff8082111561240e57600080fd5b61241a8a838b016122af565b9750602089013591508082111561243057600080fd5b61243c8a838b016122af565b965061244a60408a01612318565b9550606089013591508082111561246057600080fd5b61246c8a838b01612374565b945061247a60808a016123c5565b935060a089013591508082111561249057600080fd5b5061249d89828a01612374565b9150509295509295509295565b6000602082840312156124bc57600080fd5b8135611fdb81611fe2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610884576108846124f6565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612569576125696124f6565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600181811c908216806125b357607f821691505b6020821081036125ec577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60ff818116838216029081169081811461260e5761260e6124f6565b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b63ffffffff81811683821601908082111561260e5761260e6124f6565b600081518084526020808501945080840160005b838110156126d657815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016126a4565b509495945050505050565b600061012063ffffffff808d1684528b6020850152808b166040850152508060608401526127118184018a612690565b905082810360808401526127258189612690565b905060ff871660a084015282810360c08401526127428187611f7e565b905067ffffffffffffffff851660e08401528281036101008401526127678185611f7e565b9c9b505050505050505050505050565b60008060006060848603121561278c57600080fd5b8351925060208085015167ffffffffffffffff808211156127ac57600080fd5b818701915087601f8301126127c057600080fd5b81516127ce6122d08261232e565b81815289858386010111156127e257600080fd5b6127f182868301878701611f5a565b60408901519096509250508082111561280957600080fd5b508501601f8101871361281b57600080fd5b80516128296122d08261228b565b81815260059190911b8201830190838101908983111561284857600080fd5b928401925b828410156128665783518252928401929084019061284d565b80955050505050509250925092565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006128a46040830184611f7e565b949350505050565b601f8211156128f657600081815260208120601f850160051c810160208610156128d35750805b601f850160051c820191505b818110156128f2578281556001016128df565b5050505b505050565b815167ffffffffffffffff8111156129155761291561220d565b61292981612923845461259f565b846128ac565b602080601f83116001811461297c57600084156129465750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556128f2565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156129c9578886015182559484019460019091019084016129aa565b5085821015612a0557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8082028115828204841417610884576108846124f6565b80820180821115610884576108846124f6565b60ff8181168382160190811115610884576108846124f6565b600060ff831680612a92577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8060ff84160491505092915050565b8183823760009101908152919050565b828152606082602083013760800192915050565b600060208284031215612ad757600080fd5b5051919050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152612b258285018b612690565b91508382036080850152612b39828a612690565b915060ff881660a085015283820360c0850152612b568288611f7e565b90861660e085015283810361010085015290506127678185611f7e56fea164736f6c6343000813000a", +} + +var DKGABI = DKGMetaData.ABI + +var DKGBin = DKGMetaData.Bin + +func DeployDKG(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *DKG, error) { + parsed, err := DKGMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(DKGBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &DKG{DKGCaller: DKGCaller{contract: contract}, DKGTransactor: DKGTransactor{contract: contract}, DKGFilterer: DKGFilterer{contract: contract}}, nil +} + +type DKG struct { + address common.Address + abi abi.ABI + DKGCaller + DKGTransactor + DKGFilterer +} + +type DKGCaller struct { + contract *bind.BoundContract +} + +type DKGTransactor struct { + contract *bind.BoundContract +} + +type DKGFilterer struct { + contract *bind.BoundContract +} + +type DKGSession struct { + Contract *DKG + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type DKGCallerSession struct { + Contract *DKGCaller + CallOpts bind.CallOpts +} + +type DKGTransactorSession struct { + Contract *DKGTransactor + TransactOpts bind.TransactOpts +} + +type DKGRaw struct { + Contract *DKG +} + +type DKGCallerRaw struct { + Contract *DKGCaller +} + +type DKGTransactorRaw struct { + Contract *DKGTransactor +} + +func NewDKG(address common.Address, backend bind.ContractBackend) (*DKG, error) { + abi, err := abi.JSON(strings.NewReader(DKGABI)) + if err != nil { + return nil, err + } + contract, err := bindDKG(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &DKG{address: address, abi: abi, DKGCaller: DKGCaller{contract: contract}, DKGTransactor: DKGTransactor{contract: contract}, DKGFilterer: DKGFilterer{contract: contract}}, nil +} + +func NewDKGCaller(address common.Address, caller bind.ContractCaller) (*DKGCaller, error) { + contract, err := bindDKG(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &DKGCaller{contract: contract}, nil +} + +func NewDKGTransactor(address common.Address, transactor bind.ContractTransactor) (*DKGTransactor, error) { + contract, err := bindDKG(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &DKGTransactor{contract: contract}, nil +} + +func NewDKGFilterer(address common.Address, filterer bind.ContractFilterer) (*DKGFilterer, error) { + contract, err := bindDKG(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &DKGFilterer{contract: contract}, nil +} + +func bindDKG(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := DKGMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_DKG *DKGRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _DKG.Contract.DKGCaller.contract.Call(opts, result, method, params...) +} + +func (_DKG *DKGRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _DKG.Contract.DKGTransactor.contract.Transfer(opts) +} + +func (_DKG *DKGRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _DKG.Contract.DKGTransactor.contract.Transact(opts, method, params...) +} + +func (_DKG *DKGCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _DKG.Contract.contract.Call(opts, result, method, params...) +} + +func (_DKG *DKGTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _DKG.Contract.contract.Transfer(opts) +} + +func (_DKG *DKGTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _DKG.Contract.contract.Transact(opts, method, params...) +} + +func (_DKG *DKGCaller) GetKey(opts *bind.CallOpts, _keyID [32]byte, _configDigest [32]byte) (KeyDataStructKeyData, error) { + var out []interface{} + err := _DKG.contract.Call(opts, &out, "getKey", _keyID, _configDigest) + + if err != nil { + return *new(KeyDataStructKeyData), err + } + + out0 := *abi.ConvertType(out[0], new(KeyDataStructKeyData)).(*KeyDataStructKeyData) + + return out0, err + +} + +func (_DKG *DKGSession) GetKey(_keyID [32]byte, _configDigest [32]byte) (KeyDataStructKeyData, error) { + return _DKG.Contract.GetKey(&_DKG.CallOpts, _keyID, _configDigest) +} + +func (_DKG *DKGCallerSession) GetKey(_keyID [32]byte, _configDigest [32]byte) (KeyDataStructKeyData, error) { + return _DKG.Contract.GetKey(&_DKG.CallOpts, _keyID, _configDigest) +} + +func (_DKG *DKGCaller) LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, + + error) { + var out []interface{} + err := _DKG.contract.Call(opts, &out, "latestConfigDetails") + + outstruct := new(LatestConfigDetails) + if err != nil { + return *outstruct, err + } + + outstruct.ConfigCount = *abi.ConvertType(out[0], new(uint32)).(*uint32) + outstruct.BlockNumber = *abi.ConvertType(out[1], new(uint32)).(*uint32) + outstruct.ConfigDigest = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte) + + return *outstruct, err + +} + +func (_DKG *DKGSession) LatestConfigDetails() (LatestConfigDetails, + + error) { + return _DKG.Contract.LatestConfigDetails(&_DKG.CallOpts) +} + +func (_DKG *DKGCallerSession) LatestConfigDetails() (LatestConfigDetails, + + error) { + return _DKG.Contract.LatestConfigDetails(&_DKG.CallOpts) +} + +func (_DKG *DKGCaller) LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, + + error) { + var out []interface{} + err := _DKG.contract.Call(opts, &out, "latestConfigDigestAndEpoch") + + outstruct := new(LatestConfigDigestAndEpoch) + if err != nil { + return *outstruct, err + } + + outstruct.ScanLogs = *abi.ConvertType(out[0], new(bool)).(*bool) + outstruct.ConfigDigest = *abi.ConvertType(out[1], new([32]byte)).(*[32]byte) + outstruct.Epoch = *abi.ConvertType(out[2], new(uint32)).(*uint32) + + return *outstruct, err + +} + +func (_DKG *DKGSession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, + + error) { + return _DKG.Contract.LatestConfigDigestAndEpoch(&_DKG.CallOpts) +} + +func (_DKG *DKGCallerSession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, + + error) { + return _DKG.Contract.LatestConfigDigestAndEpoch(&_DKG.CallOpts) +} + +func (_DKG *DKGCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _DKG.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_DKG *DKGSession) Owner() (common.Address, error) { + return _DKG.Contract.Owner(&_DKG.CallOpts) +} + +func (_DKG *DKGCallerSession) Owner() (common.Address, error) { + return _DKG.Contract.Owner(&_DKG.CallOpts) +} + +func (_DKG *DKGCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _DKG.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_DKG *DKGSession) TypeAndVersion() (string, error) { + return _DKG.Contract.TypeAndVersion(&_DKG.CallOpts) +} + +func (_DKG *DKGCallerSession) TypeAndVersion() (string, error) { + return _DKG.Contract.TypeAndVersion(&_DKG.CallOpts) +} + +func (_DKG *DKGTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _DKG.contract.Transact(opts, "acceptOwnership") +} + +func (_DKG *DKGSession) AcceptOwnership() (*types.Transaction, error) { + return _DKG.Contract.AcceptOwnership(&_DKG.TransactOpts) +} + +func (_DKG *DKGTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _DKG.Contract.AcceptOwnership(&_DKG.TransactOpts) +} + +func (_DKG *DKGTransactor) AddClient(opts *bind.TransactOpts, keyID [32]byte, clientAddress common.Address) (*types.Transaction, error) { + return _DKG.contract.Transact(opts, "addClient", keyID, clientAddress) +} + +func (_DKG *DKGSession) AddClient(keyID [32]byte, clientAddress common.Address) (*types.Transaction, error) { + return _DKG.Contract.AddClient(&_DKG.TransactOpts, keyID, clientAddress) +} + +func (_DKG *DKGTransactorSession) AddClient(keyID [32]byte, clientAddress common.Address) (*types.Transaction, error) { + return _DKG.Contract.AddClient(&_DKG.TransactOpts, keyID, clientAddress) +} + +func (_DKG *DKGTransactor) RemoveClient(opts *bind.TransactOpts, keyID [32]byte, clientAddress common.Address) (*types.Transaction, error) { + return _DKG.contract.Transact(opts, "removeClient", keyID, clientAddress) +} + +func (_DKG *DKGSession) RemoveClient(keyID [32]byte, clientAddress common.Address) (*types.Transaction, error) { + return _DKG.Contract.RemoveClient(&_DKG.TransactOpts, keyID, clientAddress) +} + +func (_DKG *DKGTransactorSession) RemoveClient(keyID [32]byte, clientAddress common.Address) (*types.Transaction, error) { + return _DKG.Contract.RemoveClient(&_DKG.TransactOpts, keyID, clientAddress) +} + +func (_DKG *DKGTransactor) SetConfig(opts *bind.TransactOpts, _signers []common.Address, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*types.Transaction, error) { + return _DKG.contract.Transact(opts, "setConfig", _signers, _transmitters, _f, _onchainConfig, _offchainConfigVersion, _offchainConfig) +} + +func (_DKG *DKGSession) SetConfig(_signers []common.Address, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*types.Transaction, error) { + return _DKG.Contract.SetConfig(&_DKG.TransactOpts, _signers, _transmitters, _f, _onchainConfig, _offchainConfigVersion, _offchainConfig) +} + +func (_DKG *DKGTransactorSession) SetConfig(_signers []common.Address, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*types.Transaction, error) { + return _DKG.Contract.SetConfig(&_DKG.TransactOpts, _signers, _transmitters, _f, _onchainConfig, _offchainConfigVersion, _offchainConfig) +} + +func (_DKG *DKGTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _DKG.contract.Transact(opts, "transferOwnership", to) +} + +func (_DKG *DKGSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _DKG.Contract.TransferOwnership(&_DKG.TransactOpts, to) +} + +func (_DKG *DKGTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _DKG.Contract.TransferOwnership(&_DKG.TransactOpts, to) +} + +func (_DKG *DKGTransactor) Transmit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { + return _DKG.contract.Transact(opts, "transmit", reportContext, report, rs, ss, rawVs) +} + +func (_DKG *DKGSession) Transmit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { + return _DKG.Contract.Transmit(&_DKG.TransactOpts, reportContext, report, rs, ss, rawVs) +} + +func (_DKG *DKGTransactorSession) Transmit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { + return _DKG.Contract.Transmit(&_DKG.TransactOpts, reportContext, report, rs, ss, rawVs) +} + +type DKGConfigSetIterator struct { + Event *DKGConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *DKGConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(DKGConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(DKGConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *DKGConfigSetIterator) Error() error { + return it.fail +} + +func (it *DKGConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type DKGConfigSet struct { + PreviousConfigBlockNumber uint32 + ConfigDigest [32]byte + ConfigCount uint64 + Signers []common.Address + Transmitters []common.Address + F uint8 + OnchainConfig []byte + OffchainConfigVersion uint64 + OffchainConfig []byte + Raw types.Log +} + +func (_DKG *DKGFilterer) FilterConfigSet(opts *bind.FilterOpts) (*DKGConfigSetIterator, error) { + + logs, sub, err := _DKG.contract.FilterLogs(opts, "ConfigSet") + if err != nil { + return nil, err + } + return &DKGConfigSetIterator{contract: _DKG.contract, event: "ConfigSet", logs: logs, sub: sub}, nil +} + +func (_DKG *DKGFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *DKGConfigSet) (event.Subscription, error) { + + logs, sub, err := _DKG.contract.WatchLogs(opts, "ConfigSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(DKGConfigSet) + if err := _DKG.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_DKG *DKGFilterer) ParseConfigSet(log types.Log) (*DKGConfigSet, error) { + event := new(DKGConfigSet) + if err := _DKG.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type DKGDKGClientErrorIterator struct { + Event *DKGDKGClientError + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *DKGDKGClientErrorIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(DKGDKGClientError) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(DKGDKGClientError) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *DKGDKGClientErrorIterator) Error() error { + return it.fail +} + +func (it *DKGDKGClientErrorIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type DKGDKGClientError struct { + Client common.Address + ErrorData []byte + Raw types.Log +} + +func (_DKG *DKGFilterer) FilterDKGClientError(opts *bind.FilterOpts) (*DKGDKGClientErrorIterator, error) { + + logs, sub, err := _DKG.contract.FilterLogs(opts, "DKGClientError") + if err != nil { + return nil, err + } + return &DKGDKGClientErrorIterator{contract: _DKG.contract, event: "DKGClientError", logs: logs, sub: sub}, nil +} + +func (_DKG *DKGFilterer) WatchDKGClientError(opts *bind.WatchOpts, sink chan<- *DKGDKGClientError) (event.Subscription, error) { + + logs, sub, err := _DKG.contract.WatchLogs(opts, "DKGClientError") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(DKGDKGClientError) + if err := _DKG.contract.UnpackLog(event, "DKGClientError", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_DKG *DKGFilterer) ParseDKGClientError(log types.Log) (*DKGDKGClientError, error) { + event := new(DKGDKGClientError) + if err := _DKG.contract.UnpackLog(event, "DKGClientError", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type DKGKeyGeneratedIterator struct { + Event *DKGKeyGenerated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *DKGKeyGeneratedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(DKGKeyGenerated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(DKGKeyGenerated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *DKGKeyGeneratedIterator) Error() error { + return it.fail +} + +func (it *DKGKeyGeneratedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type DKGKeyGenerated struct { + ConfigDigest [32]byte + KeyID [32]byte + Key KeyDataStructKeyData + Raw types.Log +} + +func (_DKG *DKGFilterer) FilterKeyGenerated(opts *bind.FilterOpts, configDigest [][32]byte, keyID [][32]byte) (*DKGKeyGeneratedIterator, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + var keyIDRule []interface{} + for _, keyIDItem := range keyID { + keyIDRule = append(keyIDRule, keyIDItem) + } + + logs, sub, err := _DKG.contract.FilterLogs(opts, "KeyGenerated", configDigestRule, keyIDRule) + if err != nil { + return nil, err + } + return &DKGKeyGeneratedIterator{contract: _DKG.contract, event: "KeyGenerated", logs: logs, sub: sub}, nil +} + +func (_DKG *DKGFilterer) WatchKeyGenerated(opts *bind.WatchOpts, sink chan<- *DKGKeyGenerated, configDigest [][32]byte, keyID [][32]byte) (event.Subscription, error) { + + var configDigestRule []interface{} + for _, configDigestItem := range configDigest { + configDigestRule = append(configDigestRule, configDigestItem) + } + var keyIDRule []interface{} + for _, keyIDItem := range keyID { + keyIDRule = append(keyIDRule, keyIDItem) + } + + logs, sub, err := _DKG.contract.WatchLogs(opts, "KeyGenerated", configDigestRule, keyIDRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(DKGKeyGenerated) + if err := _DKG.contract.UnpackLog(event, "KeyGenerated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_DKG *DKGFilterer) ParseKeyGenerated(log types.Log) (*DKGKeyGenerated, error) { + event := new(DKGKeyGenerated) + if err := _DKG.contract.UnpackLog(event, "KeyGenerated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type DKGOwnershipTransferRequestedIterator struct { + Event *DKGOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *DKGOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(DKGOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(DKGOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *DKGOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *DKGOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type DKGOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_DKG *DKGFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*DKGOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _DKG.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &DKGOwnershipTransferRequestedIterator{contract: _DKG.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_DKG *DKGFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *DKGOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _DKG.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(DKGOwnershipTransferRequested) + if err := _DKG.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_DKG *DKGFilterer) ParseOwnershipTransferRequested(log types.Log) (*DKGOwnershipTransferRequested, error) { + event := new(DKGOwnershipTransferRequested) + if err := _DKG.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type DKGOwnershipTransferredIterator struct { + Event *DKGOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *DKGOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(DKGOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(DKGOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *DKGOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *DKGOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type DKGOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_DKG *DKGFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*DKGOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _DKG.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &DKGOwnershipTransferredIterator{contract: _DKG.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_DKG *DKGFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *DKGOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _DKG.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(DKGOwnershipTransferred) + if err := _DKG.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_DKG *DKGFilterer) ParseOwnershipTransferred(log types.Log) (*DKGOwnershipTransferred, error) { + event := new(DKGOwnershipTransferred) + if err := _DKG.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type DKGTransmittedIterator struct { + Event *DKGTransmitted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *DKGTransmittedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(DKGTransmitted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(DKGTransmitted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *DKGTransmittedIterator) Error() error { + return it.fail +} + +func (it *DKGTransmittedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type DKGTransmitted struct { + ConfigDigest [32]byte + Epoch uint32 + Raw types.Log +} + +func (_DKG *DKGFilterer) FilterTransmitted(opts *bind.FilterOpts) (*DKGTransmittedIterator, error) { + + logs, sub, err := _DKG.contract.FilterLogs(opts, "Transmitted") + if err != nil { + return nil, err + } + return &DKGTransmittedIterator{contract: _DKG.contract, event: "Transmitted", logs: logs, sub: sub}, nil +} + +func (_DKG *DKGFilterer) WatchTransmitted(opts *bind.WatchOpts, sink chan<- *DKGTransmitted) (event.Subscription, error) { + + logs, sub, err := _DKG.contract.WatchLogs(opts, "Transmitted") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(DKGTransmitted) + if err := _DKG.contract.UnpackLog(event, "Transmitted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_DKG *DKGFilterer) ParseTransmitted(log types.Log) (*DKGTransmitted, error) { + event := new(DKGTransmitted) + if err := _DKG.contract.UnpackLog(event, "Transmitted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type LatestConfigDetails struct { + ConfigCount uint32 + BlockNumber uint32 + ConfigDigest [32]byte +} +type LatestConfigDigestAndEpoch struct { + ScanLogs bool + ConfigDigest [32]byte + Epoch uint32 +} + +func (_DKG *DKG) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _DKG.abi.Events["ConfigSet"].ID: + return _DKG.ParseConfigSet(log) + case _DKG.abi.Events["DKGClientError"].ID: + return _DKG.ParseDKGClientError(log) + case _DKG.abi.Events["KeyGenerated"].ID: + return _DKG.ParseKeyGenerated(log) + case _DKG.abi.Events["OwnershipTransferRequested"].ID: + return _DKG.ParseOwnershipTransferRequested(log) + case _DKG.abi.Events["OwnershipTransferred"].ID: + return _DKG.ParseOwnershipTransferred(log) + case _DKG.abi.Events["Transmitted"].ID: + return _DKG.ParseTransmitted(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (DKGConfigSet) Topic() common.Hash { + return common.HexToHash("0x1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05") +} + +func (DKGDKGClientError) Topic() common.Hash { + return common.HexToHash("0x116391732f5df106193bda7cedf1728f3b07b62f6cdcdd611c9eeec44efcae54") +} + +func (DKGKeyGenerated) Topic() common.Hash { + return common.HexToHash("0xc8db841f5b2231ccf7190311f440aa197b161e369f3b40b023508160cc555656") +} + +func (DKGOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (DKGOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (DKGTransmitted) Topic() common.Hash { + return common.HexToHash("0xb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62") +} + +func (_DKG *DKG) Address() common.Address { + return _DKG.address +} + +type DKGInterface interface { + GetKey(opts *bind.CallOpts, _keyID [32]byte, _configDigest [32]byte) (KeyDataStructKeyData, error) + + LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, + + error) + + LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, + + error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + AddClient(opts *bind.TransactOpts, keyID [32]byte, clientAddress common.Address) (*types.Transaction, error) + + RemoveClient(opts *bind.TransactOpts, keyID [32]byte, clientAddress common.Address) (*types.Transaction, error) + + SetConfig(opts *bind.TransactOpts, _signers []common.Address, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + Transmit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) + + FilterConfigSet(opts *bind.FilterOpts) (*DKGConfigSetIterator, error) + + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *DKGConfigSet) (event.Subscription, error) + + ParseConfigSet(log types.Log) (*DKGConfigSet, error) + + FilterDKGClientError(opts *bind.FilterOpts) (*DKGDKGClientErrorIterator, error) + + WatchDKGClientError(opts *bind.WatchOpts, sink chan<- *DKGDKGClientError) (event.Subscription, error) + + ParseDKGClientError(log types.Log) (*DKGDKGClientError, error) + + FilterKeyGenerated(opts *bind.FilterOpts, configDigest [][32]byte, keyID [][32]byte) (*DKGKeyGeneratedIterator, error) + + WatchKeyGenerated(opts *bind.WatchOpts, sink chan<- *DKGKeyGenerated, configDigest [][32]byte, keyID [][32]byte) (event.Subscription, error) + + ParseKeyGenerated(log types.Log) (*DKGKeyGenerated, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*DKGOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *DKGOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*DKGOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*DKGOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *DKGOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*DKGOwnershipTransferred, error) + + FilterTransmitted(opts *bind.FilterOpts) (*DKGTransmittedIterator, error) + + WatchTransmitted(opts *bind.WatchOpts, sink chan<- *DKGTransmitted) (event.Subscription, error) + + ParseTransmitted(log types.Log) (*DKGTransmitted, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ocr2vrf/generated/load_test_beacon_consumer/load_test_beacon_consumer.go b/core/gethwrappers/ocr2vrf/generated/load_test_beacon_consumer/load_test_beacon_consumer.go new file mode 100644 index 00000000000..32bf1e66219 --- /dev/null +++ b/core/gethwrappers/ocr2vrf/generated/load_test_beacon_consumer/load_test_beacon_consumer.go @@ -0,0 +1,1422 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package load_test_beacon_consumer + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var LoadTestBeaconVRFConsumerMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"shouldFail\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"beaconPeriodBlocks\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"MustBeCoordinator\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeOwnerOrCoordinator\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"}],\"name\":\"CoordinatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fail\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"reqID\",\"type\":\"uint256\"}],\"name\":\"getFulfillmentDurationByRequestID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"reqID\",\"type\":\"uint256\"}],\"name\":\"getRawFulfillmentDurationByRequestID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_beaconPeriodBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingRequests\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"randomWords\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"}],\"name\":\"rawFulfillRandomWords\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"requestHeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"reset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_ReceivedRandomnessByRequestID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_arguments\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_averageFulfillmentInMillions\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_fastestFulfillment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_fulfillmentDurationInBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_gasAvailable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_mostRecentRequestID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_myBeaconRequests\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"slotNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelay\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_randomWords\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_rawFulfillmentDurationInBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_requestIDs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_requestOutputHeights\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"\",\"type\":\"uint24\"}],\"name\":\"s_requestsIDs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_resetCounter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_slowestFulfillment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_slowestRequestID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_subId\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_totalFulfilled\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_totalRequests\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"}],\"name\":\"setCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"shouldFail\",\"type\":\"bool\"}],\"name\":\"setFail\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"reqId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"height\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"delay\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"}],\"name\":\"storeBeaconRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"}],\"name\":\"testRedeemRandomness\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelayArg\",\"type\":\"uint24\"}],\"name\":\"testRequestRandomness\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"uint24\",\"name\":\"confDelay\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"}],\"name\":\"testRequestRandomnessFulfillment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelayArg\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"batchSize\",\"type\":\"uint256\"}],\"name\":\"testRequestRandomnessFulfillmentBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60806040526000600d556000600e556103e7600f556000601055600060115560006012553480156200003057600080fd5b5060405162001f6138038062001f618339810160408190526200005391620001d0565b828282823380600081620000ae5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000e157620000e18162000125565b5050600280546001600160a01b0319166001600160a01b03939093169290921790915550600b805460ff191692151592909217909155600c55506200022792505050565b336001600160a01b038216036200017f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620000a5565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600080600060608486031215620001e657600080fd5b83516001600160a01b0381168114620001fe57600080fd5b602085015190935080151581146200021557600080fd5b80925050604084015190509250925092565b611d2a80620002376000396000f3fe608060405234801561001057600080fd5b50600436106102775760003560e01c806379ba509711610160578063d0705f04116100d8578063f2fde38b1161008c578063f6eaffc811610071578063f6eaffc8146105bc578063fc7fea37146105cf578063ffe97ca4146105d857600080fd5b8063f2fde38b1461057e578063f371829b1461059157600080fd5b8063d826f88f116100bd578063d826f88f1461055a578063ea7502ab14610562578063f08c5daa1461057557600080fd5b8063d0705f0414610534578063d21ea8fd1461054757600080fd5b80638ea981171161012f578063a9cc471811610114578063a9cc4718146104fb578063c6d6130114610518578063cd0593df1461052b57600080fd5b80638ea98117146104a95780639d769402146104bc57600080fd5b806379ba5097146104675780638866c6bd1461046f5780638d0e3165146104785780638da5cb5b1461048157600080fd5b80635a947873116101f35780636df57cc3116101c2578063737144bc116101a7578063737144bc1461044057806374dba124146104495780637716cdaa1461045257600080fd5b80636df57cc314610400578063706da1ca1461041357600080fd5b80635a947873146103b05780635f15cccc146103c3578063601201d3146103ee578063689b77ab146103f757600080fd5b80632b1a21301161024a578063341867a21161022f578063341867a21461035b578063353e0f60146103705780634a0aee291461039b57600080fd5b80632b1a21301461031d5780632fe8fa311461033057600080fd5b80631591950a1461027c5780631757f11c146102ba578063195e0d75146102c35780631e87f20e146102f0575b600080fd5b6102a761028a366004611503565b601560209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6102a7600e5481565b6102a76102d1366004611525565b6012546000908152601860209081526040808320938352929052205490565b6102a76102fe366004611525565b6012546000908152601760209081526040808320938352929052205490565b6102a761032b366004611503565b61068b565b6102a761033e366004611503565b601760209081526000928352604080842090915290825290205481565b61036e610369366004611503565b6106bc565b005b6102a761037e366004611503565b601660209081526000928352604080842090915290825290205481565b6103a36107b1565b6040516102b1919061153e565b6103a36103be3660046116cc565b6108c1565b6102a76103d136600461174d565b600460209081526000928352604080842090915290825290205481565b6102a760115481565b6102a760085481565b61036e61040e366004611779565b610a1f565b6009546104279067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016102b1565b6102a7600d5481565b6102a7600f5481565b61045a610b5a565b6040516102b19190611823565b61036e610be8565b6102a760105481565b6102a760135481565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102b1565b61036e6104b736600461183d565b610cea565b61036e6104ca366004611873565b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b600b546105089060ff1681565b60405190151581526020016102b1565b6102a7610526366004611895565b610dd0565b6102a7600c5481565b6102a7610542366004611503565b610eda565b61036e6105553660046118f5565b610ef6565b61036e610f57565b6102a76105703660046119be565b610f8d565b6102a7600a5481565b61036e61058c36600461183d565b61109d565b6102a761059f366004611503565b601860209081526000928352604080842090915290825290205481565b6102a76105ca366004611525565b6110b1565b6102a760125481565b6106416105e6366004611525565b60056020526000908152604090205463ffffffff811690640100000000810462ffffff1690670100000000000000810461ffff16906901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1684565b6040805163ffffffff909516855262ffffff909316602085015261ffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff1660608201526080016102b1565b601460205281600052604060002081815481106106a757600080fd5b90600052602060002001600091509150505481565b60025460408051602081018252600080825291517facfc6cdd000000000000000000000000000000000000000000000000000000008152919273ffffffffffffffffffffffffffffffffffffffff169163acfc6cdd916107229187918791600401611a37565b6000604051808303816000875af1158015610741573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526107879190810190611a5f565b600083815260066020908152604090912082519293506107ab9290918401906114a3565b50505050565b6012546000908152601460205260408120546060919067ffffffffffffffff8111156107df576107df6115c0565b604051908082528060200260200182016040528015610808578160200160208202803683370190505b5090506000805b6012546000908152601460205260409020548110156108b957601254600090815260146020526040812080548390811061084b5761084b611af0565b600091825260208083209091015460125483526017825260408084208285529092529082205490925090036108a6578084848151811061088d5761088d611af0565b6020908102919091010152826108a281611b4e565b9350505b50806108b181611b4e565b91505061080f565b508152919050565b606060008267ffffffffffffffff8111156108de576108de6115c0565b604051908082528060200260200182016040528015610907578160200160208202803683370190505b5090506000600c546109176110d2565b6109219190611bb5565b9050600081600c546109316110d2565b61093b9190611bc9565b6109459190611be2565b905060005b85811015610a105760006109618c8c8c8c8c610f8d565b60108054919250600061097383611b4e565b90915550506012546000908152601560209081526040808320848452909152902083905561099f6110d2565b60128054600090815260166020908152604080832086845282528083209490945591548152601482529182208054600181018255908352912001819055845181908690849081106109f2576109f2611af0565b60209081029190910101525080610a0881611b4e565b91505061094a565b50919998505050505050505050565b600083815260046020908152604080832062ffffff861684529091528120859055600c54610a4d9085611bf5565b6040805160808101825263ffffffff928316815262ffffff958616602080830191825261ffff968716838501908152306060850190815260009b8c526005909252939099209151825491519351995173ffffffffffffffffffffffffffffffffffffffff166901000000000000000000027fffffff0000000000000000000000000000000000000000ffffffffffffffffff9a90971667010000000000000002999099167fffffff00000000000000000000000000000000000000000000ffffffffffffff93909716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000009091169890931697909717919091171692909217179092555050565b60078054610b6790611c09565b80601f0160208091040260200160405190810160405280929190818152602001828054610b9390611c09565b8015610be05780601f10610bb557610100808354040283529160200191610be0565b820191906000526020600020905b815481529060010190602001808311610bc357829003601f168201915b505050505081565b60015473ffffffffffffffffffffffffffffffffffffffff163314610c6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60005473ffffffffffffffffffffffffffffffffffffffff163314801590610d2a575060025473ffffffffffffffffffffffffffffffffffffffff163314155b15610d61576040517fd4e06fd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fc258faa9a17ddfdf4130b4acff63a289202e7d5f9e42f366add65368575486bc90600090a250565b600080600c54610dde6110d2565b610de89190611bb5565b9050600081600c54610df86110d2565b610e029190611bc9565b610e0c9190611be2565b60025460408051602081018252600080825291517f4ffac83a000000000000000000000000000000000000000000000000000000008152939450909273ffffffffffffffffffffffffffffffffffffffff90921691634ffac83a91610e7a918a918c918b9190600401611c5c565b6020604051808303816000875af1158015610e99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ebd9190611c94565b9050610ecb8183878a610a1f565b60088190559695505050505050565b600660205281600052604060002081815481106106a757600080fd5b60025473ffffffffffffffffffffffffffffffffffffffff163314610f47576040517f66bf9c7200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f52838383611169565b505050565b6000600d819055600e8190556103e7600f556010819055601181905560138190556012805491610f8683611b4e565b9190505550565b600080600c54610f9b6110d2565b610fa59190611bb5565b9050600081600c54610fb56110d2565b610fbf9190611bc9565b610fc99190611be2565b60025460408051602081018252600080825291517fdb972c8b000000000000000000000000000000000000000000000000000000008152939450909273ffffffffffffffffffffffffffffffffffffffff9092169163db972c8b9161103b918d918d918d918d918d9190600401611cad565b6020604051808303816000875af115801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e9190611c94565b905061108c8183898b610a1f565b600881905598975050505050505050565b6110a561132b565b6110ae816113ae565b50565b600381815481106110c157600080fd5b600091825260209091200154905081565b60004661a4b18114806110e7575062066eed81145b1561116257606473ffffffffffffffffffffffffffffffffffffffff1663a3b1b31d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611138573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115c9190611c94565b91505090565b4391505090565b600b5460ff16156111d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f206661696c656420696e2066756c66696c6c52616e646f6d576f7264730000006044820152606401610c65565b600083815260066020908152604090912083516111f5928501906114a3565b50601254600090815260156020908152604080832086845290915281205461121b6110d2565b6112259190611be2565b60125460009081526016602090815260408083208884529091528120549192509061124e6110d2565b6112589190611be2565b9050600061126983620f4240611d06565b9050600e5483111561128057600e83905560138690555b600f54831061129157600f54611293565b825b600f556011546112a357806112d6565b6011546112b1906001611bc9565b81601154600d546112c29190611d06565b6112cc9190611bc9565b6112d69190611bf5565b600d55601180549060006112e983611b4e565b90915550506012805460009081526017602090815260408083208a84528252808320969096559154815260188252848120978152969052509320929092555050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146113ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610c65565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361142d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610c65565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b8280548282559060005260206000209081019282156114de579160200282015b828111156114de5782518255916020019190600101906114c3565b506114ea9291506114ee565b5090565b5b808211156114ea57600081556001016114ef565b6000806040838503121561151657600080fd5b50508035926020909101359150565b60006020828403121561153757600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b818110156115765783518352928401929184019160010161155a565b50909695505050505050565b803561ffff8116811461159457600080fd5b919050565b803562ffffff8116811461159457600080fd5b803563ffffffff8116811461159457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611636576116366115c0565b604052919050565b600082601f83011261164f57600080fd5b813567ffffffffffffffff811115611669576116696115c0565b61169a60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016115ef565b8181528460208386010111156116af57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c087890312156116e557600080fd5b863595506116f560208801611582565b945061170360408801611599565b9350611711606088016115ac565b9250608087013567ffffffffffffffff81111561172d57600080fd5b61173989828a0161163e565b92505060a087013590509295509295509295565b6000806040838503121561176057600080fd5b8235915061177060208401611599565b90509250929050565b6000806000806080858703121561178f57600080fd5b84359350602085013592506117a660408601611599565b91506117b460608601611582565b905092959194509250565b6000815180845260005b818110156117e5576020818501810151868301820152016117c9565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061183660208301846117bf565b9392505050565b60006020828403121561184f57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461183657600080fd5b60006020828403121561188557600080fd5b8135801515811461183657600080fd5b6000806000606084860312156118aa57600080fd5b6118b384611582565b9250602084013591506118c860408501611599565b90509250925092565b600067ffffffffffffffff8211156118eb576118eb6115c0565b5060051b60200190565b60008060006060848603121561190a57600080fd5b8335925060208085013567ffffffffffffffff8082111561192a57600080fd5b818701915087601f83011261193e57600080fd5b813561195161194c826118d1565b6115ef565b81815260059190911b8301840190848101908a83111561197057600080fd5b938501935b8285101561198e57843582529385019390850190611975565b9650505060408701359250808311156119a657600080fd5b50506119b48682870161163e565b9150509250925092565b600080600080600060a086880312156119d657600080fd5b853594506119e660208701611582565b93506119f460408701611599565b9250611a02606087016115ac565b9150608086013567ffffffffffffffff811115611a1e57600080fd5b611a2a8882890161163e565b9150509295509295909350565b838152826020820152606060408201526000611a5660608301846117bf565b95945050505050565b60006020808385031215611a7257600080fd5b825167ffffffffffffffff811115611a8957600080fd5b8301601f81018513611a9a57600080fd5b8051611aa861194c826118d1565b81815260059190911b82018301908381019087831115611ac757600080fd5b928401925b82841015611ae557835182529284019290840190611acc565b979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611b7f57611b7f611b1f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611bc457611bc4611b86565b500690565b80820180821115611bdc57611bdc611b1f565b92915050565b81810381811115611bdc57611bdc611b1f565b600082611c0457611c04611b86565b500490565b600181811c90821680611c1d57607f821691505b602082108103611c56577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b84815261ffff8416602082015262ffffff83166040820152608060608201526000611c8a60808301846117bf565b9695505050505050565b600060208284031215611ca657600080fd5b5051919050565b86815261ffff8616602082015262ffffff8516604082015263ffffffff8416606082015260c060808201526000611ce760c08301856117bf565b82810360a0840152611cf981856117bf565b9998505050505050505050565b8082028115828204841417611bdc57611bdc611b1f56fea164736f6c6343000813000a", +} + +var LoadTestBeaconVRFConsumerABI = LoadTestBeaconVRFConsumerMetaData.ABI + +var LoadTestBeaconVRFConsumerBin = LoadTestBeaconVRFConsumerMetaData.Bin + +func DeployLoadTestBeaconVRFConsumer(auth *bind.TransactOpts, backend bind.ContractBackend, coordinator common.Address, shouldFail bool, beaconPeriodBlocks *big.Int) (common.Address, *types.Transaction, *LoadTestBeaconVRFConsumer, error) { + parsed, err := LoadTestBeaconVRFConsumerMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(LoadTestBeaconVRFConsumerBin), backend, coordinator, shouldFail, beaconPeriodBlocks) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &LoadTestBeaconVRFConsumer{LoadTestBeaconVRFConsumerCaller: LoadTestBeaconVRFConsumerCaller{contract: contract}, LoadTestBeaconVRFConsumerTransactor: LoadTestBeaconVRFConsumerTransactor{contract: contract}, LoadTestBeaconVRFConsumerFilterer: LoadTestBeaconVRFConsumerFilterer{contract: contract}}, nil +} + +type LoadTestBeaconVRFConsumer struct { + address common.Address + abi abi.ABI + LoadTestBeaconVRFConsumerCaller + LoadTestBeaconVRFConsumerTransactor + LoadTestBeaconVRFConsumerFilterer +} + +type LoadTestBeaconVRFConsumerCaller struct { + contract *bind.BoundContract +} + +type LoadTestBeaconVRFConsumerTransactor struct { + contract *bind.BoundContract +} + +type LoadTestBeaconVRFConsumerFilterer struct { + contract *bind.BoundContract +} + +type LoadTestBeaconVRFConsumerSession struct { + Contract *LoadTestBeaconVRFConsumer + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type LoadTestBeaconVRFConsumerCallerSession struct { + Contract *LoadTestBeaconVRFConsumerCaller + CallOpts bind.CallOpts +} + +type LoadTestBeaconVRFConsumerTransactorSession struct { + Contract *LoadTestBeaconVRFConsumerTransactor + TransactOpts bind.TransactOpts +} + +type LoadTestBeaconVRFConsumerRaw struct { + Contract *LoadTestBeaconVRFConsumer +} + +type LoadTestBeaconVRFConsumerCallerRaw struct { + Contract *LoadTestBeaconVRFConsumerCaller +} + +type LoadTestBeaconVRFConsumerTransactorRaw struct { + Contract *LoadTestBeaconVRFConsumerTransactor +} + +func NewLoadTestBeaconVRFConsumer(address common.Address, backend bind.ContractBackend) (*LoadTestBeaconVRFConsumer, error) { + abi, err := abi.JSON(strings.NewReader(LoadTestBeaconVRFConsumerABI)) + if err != nil { + return nil, err + } + contract, err := bindLoadTestBeaconVRFConsumer(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &LoadTestBeaconVRFConsumer{address: address, abi: abi, LoadTestBeaconVRFConsumerCaller: LoadTestBeaconVRFConsumerCaller{contract: contract}, LoadTestBeaconVRFConsumerTransactor: LoadTestBeaconVRFConsumerTransactor{contract: contract}, LoadTestBeaconVRFConsumerFilterer: LoadTestBeaconVRFConsumerFilterer{contract: contract}}, nil +} + +func NewLoadTestBeaconVRFConsumerCaller(address common.Address, caller bind.ContractCaller) (*LoadTestBeaconVRFConsumerCaller, error) { + contract, err := bindLoadTestBeaconVRFConsumer(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &LoadTestBeaconVRFConsumerCaller{contract: contract}, nil +} + +func NewLoadTestBeaconVRFConsumerTransactor(address common.Address, transactor bind.ContractTransactor) (*LoadTestBeaconVRFConsumerTransactor, error) { + contract, err := bindLoadTestBeaconVRFConsumer(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &LoadTestBeaconVRFConsumerTransactor{contract: contract}, nil +} + +func NewLoadTestBeaconVRFConsumerFilterer(address common.Address, filterer bind.ContractFilterer) (*LoadTestBeaconVRFConsumerFilterer, error) { + contract, err := bindLoadTestBeaconVRFConsumer(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &LoadTestBeaconVRFConsumerFilterer{contract: contract}, nil +} + +func bindLoadTestBeaconVRFConsumer(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := LoadTestBeaconVRFConsumerMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _LoadTestBeaconVRFConsumer.Contract.LoadTestBeaconVRFConsumerCaller.contract.Call(opts, result, method, params...) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.LoadTestBeaconVRFConsumerTransactor.contract.Transfer(opts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.LoadTestBeaconVRFConsumerTransactor.contract.Transact(opts, method, params...) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _LoadTestBeaconVRFConsumer.Contract.contract.Call(opts, result, method, params...) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.contract.Transfer(opts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.contract.Transact(opts, method, params...) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) Fail(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "fail") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) Fail() (bool, error) { + return _LoadTestBeaconVRFConsumer.Contract.Fail(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) Fail() (bool, error) { + return _LoadTestBeaconVRFConsumer.Contract.Fail(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) GetFulfillmentDurationByRequestID(opts *bind.CallOpts, reqID *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "getFulfillmentDurationByRequestID", reqID) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) GetFulfillmentDurationByRequestID(reqID *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.GetFulfillmentDurationByRequestID(&_LoadTestBeaconVRFConsumer.CallOpts, reqID) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) GetFulfillmentDurationByRequestID(reqID *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.GetFulfillmentDurationByRequestID(&_LoadTestBeaconVRFConsumer.CallOpts, reqID) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) GetRawFulfillmentDurationByRequestID(opts *bind.CallOpts, reqID *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "getRawFulfillmentDurationByRequestID", reqID) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) GetRawFulfillmentDurationByRequestID(reqID *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.GetRawFulfillmentDurationByRequestID(&_LoadTestBeaconVRFConsumer.CallOpts, reqID) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) GetRawFulfillmentDurationByRequestID(reqID *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.GetRawFulfillmentDurationByRequestID(&_LoadTestBeaconVRFConsumer.CallOpts, reqID) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) IBeaconPeriodBlocks(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "i_beaconPeriodBlocks") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) IBeaconPeriodBlocks() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.IBeaconPeriodBlocks(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) IBeaconPeriodBlocks() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.IBeaconPeriodBlocks(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) Owner() (common.Address, error) { + return _LoadTestBeaconVRFConsumer.Contract.Owner(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) Owner() (common.Address, error) { + return _LoadTestBeaconVRFConsumer.Contract.Owner(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) PendingRequests(opts *bind.CallOpts) ([]*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "pendingRequests") + + if err != nil { + return *new([]*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) PendingRequests() ([]*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.PendingRequests(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) PendingRequests() ([]*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.PendingRequests(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) RequestHeights(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "requestHeights", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) RequestHeights(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.RequestHeights(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) RequestHeights(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.RequestHeights(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SReceivedRandomnessByRequestID(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_ReceivedRandomnessByRequestID", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SReceivedRandomnessByRequestID(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SReceivedRandomnessByRequestID(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SReceivedRandomnessByRequestID(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SReceivedRandomnessByRequestID(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SArguments(opts *bind.CallOpts) ([]byte, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_arguments") + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SArguments() ([]byte, error) { + return _LoadTestBeaconVRFConsumer.Contract.SArguments(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SArguments() ([]byte, error) { + return _LoadTestBeaconVRFConsumer.Contract.SArguments(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SAverageFulfillmentInMillions(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_averageFulfillmentInMillions") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SAverageFulfillmentInMillions() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SAverageFulfillmentInMillions(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SAverageFulfillmentInMillions() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SAverageFulfillmentInMillions(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SFastestFulfillment(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_fastestFulfillment") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SFastestFulfillment() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SFastestFulfillment(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SFastestFulfillment() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SFastestFulfillment(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SFulfillmentDurationInBlocks(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_fulfillmentDurationInBlocks", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SFulfillmentDurationInBlocks(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SFulfillmentDurationInBlocks(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SFulfillmentDurationInBlocks(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SFulfillmentDurationInBlocks(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SGasAvailable(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_gasAvailable") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SGasAvailable() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SGasAvailable(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SGasAvailable() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SGasAvailable(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SMostRecentRequestID(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_mostRecentRequestID") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SMostRecentRequestID() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SMostRecentRequestID(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SMostRecentRequestID() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SMostRecentRequestID(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SMyBeaconRequests(opts *bind.CallOpts, arg0 *big.Int) (SMyBeaconRequests, + + error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_myBeaconRequests", arg0) + + outstruct := new(SMyBeaconRequests) + if err != nil { + return *outstruct, err + } + + outstruct.SlotNumber = *abi.ConvertType(out[0], new(uint32)).(*uint32) + outstruct.ConfirmationDelay = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + outstruct.NumWords = *abi.ConvertType(out[2], new(uint16)).(*uint16) + outstruct.Requester = *abi.ConvertType(out[3], new(common.Address)).(*common.Address) + + return *outstruct, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SMyBeaconRequests(arg0 *big.Int) (SMyBeaconRequests, + + error) { + return _LoadTestBeaconVRFConsumer.Contract.SMyBeaconRequests(&_LoadTestBeaconVRFConsumer.CallOpts, arg0) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SMyBeaconRequests(arg0 *big.Int) (SMyBeaconRequests, + + error) { + return _LoadTestBeaconVRFConsumer.Contract.SMyBeaconRequests(&_LoadTestBeaconVRFConsumer.CallOpts, arg0) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SRandomWords(opts *bind.CallOpts, arg0 *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_randomWords", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SRandomWords(arg0 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRandomWords(&_LoadTestBeaconVRFConsumer.CallOpts, arg0) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SRandomWords(arg0 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRandomWords(&_LoadTestBeaconVRFConsumer.CallOpts, arg0) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SRawFulfillmentDurationInBlocks(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_rawFulfillmentDurationInBlocks", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SRawFulfillmentDurationInBlocks(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRawFulfillmentDurationInBlocks(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SRawFulfillmentDurationInBlocks(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRawFulfillmentDurationInBlocks(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SRequestIDs(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_requestIDs", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SRequestIDs(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRequestIDs(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SRequestIDs(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRequestIDs(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SRequestOutputHeights(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_requestOutputHeights", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SRequestOutputHeights(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRequestOutputHeights(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SRequestOutputHeights(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRequestOutputHeights(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SRequestsIDs(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_requestsIDs", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SRequestsIDs(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRequestsIDs(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SRequestsIDs(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SRequestsIDs(&_LoadTestBeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SResetCounter(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_resetCounter") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SResetCounter() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SResetCounter(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SResetCounter() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SResetCounter(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SSlowestFulfillment(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_slowestFulfillment") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SSlowestFulfillment() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SSlowestFulfillment(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SSlowestFulfillment() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SSlowestFulfillment(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SSlowestRequestID(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_slowestRequestID") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SSlowestRequestID() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SSlowestRequestID(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SSlowestRequestID() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.SSlowestRequestID(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) SSubId(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_subId") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SSubId() (uint64, error) { + return _LoadTestBeaconVRFConsumer.Contract.SSubId(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) SSubId() (uint64, error) { + return _LoadTestBeaconVRFConsumer.Contract.SSubId(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) STotalFulfilled(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_totalFulfilled") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) STotalFulfilled() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.STotalFulfilled(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) STotalFulfilled() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.STotalFulfilled(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCaller) STotalRequests(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _LoadTestBeaconVRFConsumer.contract.Call(opts, &out, "s_totalRequests") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) STotalRequests() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.STotalRequests(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerCallerSession) STotalRequests() (*big.Int, error) { + return _LoadTestBeaconVRFConsumer.Contract.STotalRequests(&_LoadTestBeaconVRFConsumer.CallOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "acceptOwnership") +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) AcceptOwnership() (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.AcceptOwnership(&_LoadTestBeaconVRFConsumer.TransactOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.AcceptOwnership(&_LoadTestBeaconVRFConsumer.TransactOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) RawFulfillRandomWords(opts *bind.TransactOpts, requestID *big.Int, randomWords []*big.Int, arguments []byte) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "rawFulfillRandomWords", requestID, randomWords, arguments) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) RawFulfillRandomWords(requestID *big.Int, randomWords []*big.Int, arguments []byte) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.RawFulfillRandomWords(&_LoadTestBeaconVRFConsumer.TransactOpts, requestID, randomWords, arguments) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) RawFulfillRandomWords(requestID *big.Int, randomWords []*big.Int, arguments []byte) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.RawFulfillRandomWords(&_LoadTestBeaconVRFConsumer.TransactOpts, requestID, randomWords, arguments) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) Reset(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "reset") +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) Reset() (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.Reset(&_LoadTestBeaconVRFConsumer.TransactOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) Reset() (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.Reset(&_LoadTestBeaconVRFConsumer.TransactOpts) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) SetCoordinator(opts *bind.TransactOpts, coordinator common.Address) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "setCoordinator", coordinator) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SetCoordinator(coordinator common.Address) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.SetCoordinator(&_LoadTestBeaconVRFConsumer.TransactOpts, coordinator) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) SetCoordinator(coordinator common.Address) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.SetCoordinator(&_LoadTestBeaconVRFConsumer.TransactOpts, coordinator) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) SetFail(opts *bind.TransactOpts, shouldFail bool) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "setFail", shouldFail) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) SetFail(shouldFail bool) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.SetFail(&_LoadTestBeaconVRFConsumer.TransactOpts, shouldFail) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) SetFail(shouldFail bool) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.SetFail(&_LoadTestBeaconVRFConsumer.TransactOpts, shouldFail) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) StoreBeaconRequest(opts *bind.TransactOpts, reqId *big.Int, height *big.Int, delay *big.Int, numWords uint16) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "storeBeaconRequest", reqId, height, delay, numWords) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) StoreBeaconRequest(reqId *big.Int, height *big.Int, delay *big.Int, numWords uint16) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.StoreBeaconRequest(&_LoadTestBeaconVRFConsumer.TransactOpts, reqId, height, delay, numWords) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) StoreBeaconRequest(reqId *big.Int, height *big.Int, delay *big.Int, numWords uint16) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.StoreBeaconRequest(&_LoadTestBeaconVRFConsumer.TransactOpts, reqId, height, delay, numWords) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) TestRedeemRandomness(opts *bind.TransactOpts, subID *big.Int, requestID *big.Int) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "testRedeemRandomness", subID, requestID) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) TestRedeemRandomness(subID *big.Int, requestID *big.Int) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TestRedeemRandomness(&_LoadTestBeaconVRFConsumer.TransactOpts, subID, requestID) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) TestRedeemRandomness(subID *big.Int, requestID *big.Int) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TestRedeemRandomness(&_LoadTestBeaconVRFConsumer.TransactOpts, subID, requestID) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) TestRequestRandomness(opts *bind.TransactOpts, numWords uint16, subID *big.Int, confirmationDelayArg *big.Int) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "testRequestRandomness", numWords, subID, confirmationDelayArg) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) TestRequestRandomness(numWords uint16, subID *big.Int, confirmationDelayArg *big.Int) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TestRequestRandomness(&_LoadTestBeaconVRFConsumer.TransactOpts, numWords, subID, confirmationDelayArg) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) TestRequestRandomness(numWords uint16, subID *big.Int, confirmationDelayArg *big.Int) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TestRequestRandomness(&_LoadTestBeaconVRFConsumer.TransactOpts, numWords, subID, confirmationDelayArg) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) TestRequestRandomnessFulfillment(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "testRequestRandomnessFulfillment", subID, numWords, confDelay, callbackGasLimit, arguments) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) TestRequestRandomnessFulfillment(subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TestRequestRandomnessFulfillment(&_LoadTestBeaconVRFConsumer.TransactOpts, subID, numWords, confDelay, callbackGasLimit, arguments) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) TestRequestRandomnessFulfillment(subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TestRequestRandomnessFulfillment(&_LoadTestBeaconVRFConsumer.TransactOpts, subID, numWords, confDelay, callbackGasLimit, arguments) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) TestRequestRandomnessFulfillmentBatch(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confirmationDelayArg *big.Int, callbackGasLimit uint32, arguments []byte, batchSize *big.Int) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "testRequestRandomnessFulfillmentBatch", subID, numWords, confirmationDelayArg, callbackGasLimit, arguments, batchSize) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) TestRequestRandomnessFulfillmentBatch(subID *big.Int, numWords uint16, confirmationDelayArg *big.Int, callbackGasLimit uint32, arguments []byte, batchSize *big.Int) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TestRequestRandomnessFulfillmentBatch(&_LoadTestBeaconVRFConsumer.TransactOpts, subID, numWords, confirmationDelayArg, callbackGasLimit, arguments, batchSize) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) TestRequestRandomnessFulfillmentBatch(subID *big.Int, numWords uint16, confirmationDelayArg *big.Int, callbackGasLimit uint32, arguments []byte, batchSize *big.Int) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TestRequestRandomnessFulfillmentBatch(&_LoadTestBeaconVRFConsumer.TransactOpts, subID, numWords, confirmationDelayArg, callbackGasLimit, arguments, batchSize) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.contract.Transact(opts, "transferOwnership", to) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TransferOwnership(&_LoadTestBeaconVRFConsumer.TransactOpts, to) +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _LoadTestBeaconVRFConsumer.Contract.TransferOwnership(&_LoadTestBeaconVRFConsumer.TransactOpts, to) +} + +type LoadTestBeaconVRFConsumerCoordinatorUpdatedIterator struct { + Event *LoadTestBeaconVRFConsumerCoordinatorUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *LoadTestBeaconVRFConsumerCoordinatorUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(LoadTestBeaconVRFConsumerCoordinatorUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(LoadTestBeaconVRFConsumerCoordinatorUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *LoadTestBeaconVRFConsumerCoordinatorUpdatedIterator) Error() error { + return it.fail +} + +func (it *LoadTestBeaconVRFConsumerCoordinatorUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type LoadTestBeaconVRFConsumerCoordinatorUpdated struct { + Coordinator common.Address + Raw types.Log +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerFilterer) FilterCoordinatorUpdated(opts *bind.FilterOpts, coordinator []common.Address) (*LoadTestBeaconVRFConsumerCoordinatorUpdatedIterator, error) { + + var coordinatorRule []interface{} + for _, coordinatorItem := range coordinator { + coordinatorRule = append(coordinatorRule, coordinatorItem) + } + + logs, sub, err := _LoadTestBeaconVRFConsumer.contract.FilterLogs(opts, "CoordinatorUpdated", coordinatorRule) + if err != nil { + return nil, err + } + return &LoadTestBeaconVRFConsumerCoordinatorUpdatedIterator{contract: _LoadTestBeaconVRFConsumer.contract, event: "CoordinatorUpdated", logs: logs, sub: sub}, nil +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerFilterer) WatchCoordinatorUpdated(opts *bind.WatchOpts, sink chan<- *LoadTestBeaconVRFConsumerCoordinatorUpdated, coordinator []common.Address) (event.Subscription, error) { + + var coordinatorRule []interface{} + for _, coordinatorItem := range coordinator { + coordinatorRule = append(coordinatorRule, coordinatorItem) + } + + logs, sub, err := _LoadTestBeaconVRFConsumer.contract.WatchLogs(opts, "CoordinatorUpdated", coordinatorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(LoadTestBeaconVRFConsumerCoordinatorUpdated) + if err := _LoadTestBeaconVRFConsumer.contract.UnpackLog(event, "CoordinatorUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerFilterer) ParseCoordinatorUpdated(log types.Log) (*LoadTestBeaconVRFConsumerCoordinatorUpdated, error) { + event := new(LoadTestBeaconVRFConsumerCoordinatorUpdated) + if err := _LoadTestBeaconVRFConsumer.contract.UnpackLog(event, "CoordinatorUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type LoadTestBeaconVRFConsumerOwnershipTransferRequestedIterator struct { + Event *LoadTestBeaconVRFConsumerOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *LoadTestBeaconVRFConsumerOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(LoadTestBeaconVRFConsumerOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(LoadTestBeaconVRFConsumerOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *LoadTestBeaconVRFConsumerOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *LoadTestBeaconVRFConsumerOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type LoadTestBeaconVRFConsumerOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*LoadTestBeaconVRFConsumerOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _LoadTestBeaconVRFConsumer.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &LoadTestBeaconVRFConsumerOwnershipTransferRequestedIterator{contract: _LoadTestBeaconVRFConsumer.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *LoadTestBeaconVRFConsumerOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _LoadTestBeaconVRFConsumer.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(LoadTestBeaconVRFConsumerOwnershipTransferRequested) + if err := _LoadTestBeaconVRFConsumer.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerFilterer) ParseOwnershipTransferRequested(log types.Log) (*LoadTestBeaconVRFConsumerOwnershipTransferRequested, error) { + event := new(LoadTestBeaconVRFConsumerOwnershipTransferRequested) + if err := _LoadTestBeaconVRFConsumer.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type LoadTestBeaconVRFConsumerOwnershipTransferredIterator struct { + Event *LoadTestBeaconVRFConsumerOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *LoadTestBeaconVRFConsumerOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(LoadTestBeaconVRFConsumerOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(LoadTestBeaconVRFConsumerOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *LoadTestBeaconVRFConsumerOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *LoadTestBeaconVRFConsumerOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type LoadTestBeaconVRFConsumerOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*LoadTestBeaconVRFConsumerOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _LoadTestBeaconVRFConsumer.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &LoadTestBeaconVRFConsumerOwnershipTransferredIterator{contract: _LoadTestBeaconVRFConsumer.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *LoadTestBeaconVRFConsumerOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _LoadTestBeaconVRFConsumer.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(LoadTestBeaconVRFConsumerOwnershipTransferred) + if err := _LoadTestBeaconVRFConsumer.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumerFilterer) ParseOwnershipTransferred(log types.Log) (*LoadTestBeaconVRFConsumerOwnershipTransferred, error) { + event := new(LoadTestBeaconVRFConsumerOwnershipTransferred) + if err := _LoadTestBeaconVRFConsumer.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type SMyBeaconRequests struct { + SlotNumber uint32 + ConfirmationDelay *big.Int + NumWords uint16 + Requester common.Address +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumer) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _LoadTestBeaconVRFConsumer.abi.Events["CoordinatorUpdated"].ID: + return _LoadTestBeaconVRFConsumer.ParseCoordinatorUpdated(log) + case _LoadTestBeaconVRFConsumer.abi.Events["OwnershipTransferRequested"].ID: + return _LoadTestBeaconVRFConsumer.ParseOwnershipTransferRequested(log) + case _LoadTestBeaconVRFConsumer.abi.Events["OwnershipTransferred"].ID: + return _LoadTestBeaconVRFConsumer.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (LoadTestBeaconVRFConsumerCoordinatorUpdated) Topic() common.Hash { + return common.HexToHash("0xc258faa9a17ddfdf4130b4acff63a289202e7d5f9e42f366add65368575486bc") +} + +func (LoadTestBeaconVRFConsumerOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (LoadTestBeaconVRFConsumerOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_LoadTestBeaconVRFConsumer *LoadTestBeaconVRFConsumer) Address() common.Address { + return _LoadTestBeaconVRFConsumer.address +} + +type LoadTestBeaconVRFConsumerInterface interface { + Fail(opts *bind.CallOpts) (bool, error) + + GetFulfillmentDurationByRequestID(opts *bind.CallOpts, reqID *big.Int) (*big.Int, error) + + GetRawFulfillmentDurationByRequestID(opts *bind.CallOpts, reqID *big.Int) (*big.Int, error) + + IBeaconPeriodBlocks(opts *bind.CallOpts) (*big.Int, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + PendingRequests(opts *bind.CallOpts) ([]*big.Int, error) + + RequestHeights(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) + + SReceivedRandomnessByRequestID(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) + + SArguments(opts *bind.CallOpts) ([]byte, error) + + SAverageFulfillmentInMillions(opts *bind.CallOpts) (*big.Int, error) + + SFastestFulfillment(opts *bind.CallOpts) (*big.Int, error) + + SFulfillmentDurationInBlocks(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) + + SGasAvailable(opts *bind.CallOpts) (*big.Int, error) + + SMostRecentRequestID(opts *bind.CallOpts) (*big.Int, error) + + SMyBeaconRequests(opts *bind.CallOpts, arg0 *big.Int) (SMyBeaconRequests, + + error) + + SRandomWords(opts *bind.CallOpts, arg0 *big.Int) (*big.Int, error) + + SRawFulfillmentDurationInBlocks(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) + + SRequestIDs(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) + + SRequestOutputHeights(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) + + SRequestsIDs(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) + + SResetCounter(opts *bind.CallOpts) (*big.Int, error) + + SSlowestFulfillment(opts *bind.CallOpts) (*big.Int, error) + + SSlowestRequestID(opts *bind.CallOpts) (*big.Int, error) + + SSubId(opts *bind.CallOpts) (uint64, error) + + STotalFulfilled(opts *bind.CallOpts) (*big.Int, error) + + STotalRequests(opts *bind.CallOpts) (*big.Int, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + RawFulfillRandomWords(opts *bind.TransactOpts, requestID *big.Int, randomWords []*big.Int, arguments []byte) (*types.Transaction, error) + + Reset(opts *bind.TransactOpts) (*types.Transaction, error) + + SetCoordinator(opts *bind.TransactOpts, coordinator common.Address) (*types.Transaction, error) + + SetFail(opts *bind.TransactOpts, shouldFail bool) (*types.Transaction, error) + + StoreBeaconRequest(opts *bind.TransactOpts, reqId *big.Int, height *big.Int, delay *big.Int, numWords uint16) (*types.Transaction, error) + + TestRedeemRandomness(opts *bind.TransactOpts, subID *big.Int, requestID *big.Int) (*types.Transaction, error) + + TestRequestRandomness(opts *bind.TransactOpts, numWords uint16, subID *big.Int, confirmationDelayArg *big.Int) (*types.Transaction, error) + + TestRequestRandomnessFulfillment(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte) (*types.Transaction, error) + + TestRequestRandomnessFulfillmentBatch(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confirmationDelayArg *big.Int, callbackGasLimit uint32, arguments []byte, batchSize *big.Int) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterCoordinatorUpdated(opts *bind.FilterOpts, coordinator []common.Address) (*LoadTestBeaconVRFConsumerCoordinatorUpdatedIterator, error) + + WatchCoordinatorUpdated(opts *bind.WatchOpts, sink chan<- *LoadTestBeaconVRFConsumerCoordinatorUpdated, coordinator []common.Address) (event.Subscription, error) + + ParseCoordinatorUpdated(log types.Log) (*LoadTestBeaconVRFConsumerCoordinatorUpdated, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*LoadTestBeaconVRFConsumerOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *LoadTestBeaconVRFConsumerOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*LoadTestBeaconVRFConsumerOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*LoadTestBeaconVRFConsumerOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *LoadTestBeaconVRFConsumerOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*LoadTestBeaconVRFConsumerOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ocr2vrf/generated/vrf_beacon/vrf_beacon.go b/core/gethwrappers/ocr2vrf/generated/vrf_beacon/vrf_beacon.go new file mode 100644 index 00000000000..b44019de548 --- /dev/null +++ b/core/gethwrappers/ocr2vrf/generated/vrf_beacon/vrf_beacon.go @@ -0,0 +1,2846 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package vrf_beacon + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +type ECCArithmeticG1Point struct { + P [2]*big.Int +} + +type KeyDataStructKeyData struct { + PublicKey []byte + Hashes [][32]byte +} + +type VRFBeaconReportReport struct { + Outputs []VRFBeaconTypesVRFOutput + JuelsPerFeeCoin *big.Int + ReasonableGasPrice uint64 + RecentBlockHeight uint64 + RecentBlockHash [32]byte +} + +type VRFBeaconTypesCallback struct { + RequestID *big.Int + NumWords uint16 + Requester common.Address + Arguments []byte + GasAllowance *big.Int + SubID *big.Int + GasPrice *big.Int + WeiPerUnitLink *big.Int +} + +type VRFBeaconTypesCostedCallback struct { + Callback VRFBeaconTypesCallback + Price *big.Int +} + +type VRFBeaconTypesOutputServed struct { + Height uint64 + ConfirmationDelay *big.Int + ProofG1X *big.Int + ProofG1Y *big.Int +} + +type VRFBeaconTypesVRFOutput struct { + BlockHeight uint64 + ConfirmationDelay *big.Int + VrfOutput ECCArithmeticG1Point + Callbacks []VRFBeaconTypesCostedCallback + ShouldStore bool +} + +var VRFBeaconMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"link\",\"type\":\"address\"},{\"internalType\":\"contractIVRFCoordinatorProducerAPI\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"contractDKG\",\"name\":\"keyProvider\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"keyID\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expectedLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualLength\",\"type\":\"uint256\"}],\"name\":\"CalldataLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotAcceptPayeeship\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"providedHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"onchainHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"blockHeight\",\"type\":\"uint64\"}],\"name\":\"HistoryDomainSeparatorWrong\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numTransmitters\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numPayees\",\"type\":\"uint256\"}],\"name\":\"IncorrectNumberOfPayees\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expectedNumSignatures\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"rsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"ssLength\",\"type\":\"uint256\"}],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"actualBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requiredBalance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"keyProvider\",\"type\":\"address\"}],\"name\":\"KeyInfoMustComeFromProvider\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeftGasExceedsInitialGas\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeOwnerOrBillingAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"numFaultyOracles\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"}],\"name\":\"NumberOfFaultyOraclesTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"expectedLength\",\"type\":\"uint256\"}],\"name\":\"OnchainConfigHasWrongLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCurrentPayee\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"existingPayee\",\"type\":\"address\"}],\"name\":\"PayeeAlreadySet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"repeatedSignerAddress\",\"type\":\"address\"}],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"repeatedTransmitterAddress\",\"type\":\"address\"}],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReportDoesNotContainNewOutputs\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numTransmitters\",\"type\":\"uint256\"}],\"name\":\"SignersTransmittersMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"maxOracles\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"providedOracles\",\"type\":\"uint256\"}],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"ocrVersion\",\"type\":\"uint64\"}],\"name\":\"UnknownConfigVersion\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contractAccessControllerInterface\",\"name\":\"old\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contractAccessControllerInterface\",\"name\":\"current\",\"type\":\"address\"}],\"name\":\"BillingAccessControllerSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"maximumGasPrice\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"reasonableGasPrice\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"observationPayment\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"transmissionPayment\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint24\",\"name\":\"accountingGas\",\"type\":\"uint24\"}],\"name\":\"BillingSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint40\",\"name\":\"epochAndRound\",\"type\":\"uint40\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint192\",\"name\":\"juelsPerFeeCoin\",\"type\":\"uint192\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"reasonableGasPrice\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"NewTransmission\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contractLinkTokenInterface\",\"name\":\"linkToken\",\"type\":\"address\"}],\"name\":\"OraclePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"recentBlockHeight\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint192\",\"name\":\"juelsPerFeeCoin\",\"type\":\"uint192\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"reasonableGasPrice\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"height\",\"type\":\"uint64\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelay\",\"type\":\"uint24\"},{\"internalType\":\"uint256\",\"name\":\"proofG1X\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"proofG1Y\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structVRFBeaconTypes.OutputServed[]\",\"name\":\"outputsServed\",\"type\":\"tuple[]\"}],\"name\":\"OutputsServed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"current\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previous\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"current\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"requestIDs\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"successfulFulfillment\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"truncatedErrorData\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint96[]\",\"name\":\"subBalances\",\"type\":\"uint96[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"subIDs\",\"type\":\"uint256[]\"}],\"name\":\"RandomWordsFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nextBeaconOutputHeight\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint24\",\"name\":\"confDelay\",\"type\":\"uint24\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasAllowance\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasPrice\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weiPerUnitLink\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"costJuels\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSubBalance\",\"type\":\"uint256\"}],\"name\":\"RandomnessFulfillmentRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"}],\"name\":\"RandomnessRedeemed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nextBeaconOutputHeight\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint24\",\"name\":\"confDelay\",\"type\":\"uint24\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"costJuels\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSubBalance\",\"type\":\"uint256\"}],\"name\":\"RandomnessRequested\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NUM_CONF_DELAYS\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"acceptPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"blockHeight\",\"type\":\"uint64\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelay\",\"type\":\"uint24\"},{\"components\":[{\"internalType\":\"uint256[2]\",\"name\":\"p\",\"type\":\"uint256[2]\"}],\"internalType\":\"structECCArithmetic.G1Point\",\"name\":\"vrfOutput\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"},{\"internalType\":\"uint96\",\"name\":\"gasAllowance\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weiPerUnitLink\",\"type\":\"uint256\"}],\"internalType\":\"structVRFBeaconTypes.Callback\",\"name\":\"callback\",\"type\":\"tuple\"},{\"internalType\":\"uint96\",\"name\":\"price\",\"type\":\"uint96\"}],\"internalType\":\"structVRFBeaconTypes.CostedCallback[]\",\"name\":\"callbacks\",\"type\":\"tuple[]\"},{\"internalType\":\"bool\",\"name\":\"shouldStore\",\"type\":\"bool\"}],\"internalType\":\"structVRFBeaconTypes.VRFOutput[]\",\"name\":\"outputs\",\"type\":\"tuple[]\"},{\"internalType\":\"uint192\",\"name\":\"juelsPerFeeCoin\",\"type\":\"uint192\"},{\"internalType\":\"uint64\",\"name\":\"reasonableGasPrice\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"recentBlockHeight\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"recentBlockHash\",\"type\":\"bytes32\"}],\"internalType\":\"structVRFBeaconReport.Report\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"exposeType\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBilling\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"maximumGasPrice\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"reasonableGasPrice\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"observationPayment\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"transmissionPayment\",\"type\":\"uint64\"},{\"internalType\":\"uint24\",\"name\":\"accountingGas\",\"type\":\"uint24\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBillingAccessController\",\"outputs\":[{\"internalType\":\"contractAccessControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_coordinator\",\"outputs\":[{\"internalType\":\"contractIVRFCoordinatorProducerAPI\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_link\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashes\",\"type\":\"bytes32[]\"}],\"internalType\":\"structKeyDataStruct.KeyData\",\"name\":\"kd\",\"type\":\"tuple\"}],\"name\":\"keyGenerated\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"availableBalance\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"newKeyRequested\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitterAddress\",\"type\":\"address\"}],\"name\":\"owedPayment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_keyID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_keyProvider\",\"outputs\":[{\"internalType\":\"contractDKG\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_provingKeyHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"maximumGasPrice\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"reasonableGasPrice\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"observationPayment\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"transmissionPayment\",\"type\":\"uint64\"},{\"internalType\":\"uint24\",\"name\":\"accountingGas\",\"type\":\"uint24\"}],\"name\":\"setBilling\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractAccessControllerInterface\",\"name\":\"_billingAccessController\",\"type\":\"address\"}],\"name\":\"setBillingAccessController\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"setPayees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"withdrawPayment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60e06040523480156200001157600080fd5b5060405162004dfe38038062004dfe8339810160408190526200003491620001c7565b8181858581813380600081620000915760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c457620000c48162000103565b5050506001600160a01b03918216608052811660a052600e80546001600160a01b03191695909116949094179093555060c05250620002219350505050565b336001600160a01b038216036200015d5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000088565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b0381168114620001c457600080fd5b50565b60008060008060808587031215620001de57600080fd5b8451620001eb81620001ae565b6020860151909450620001fe81620001ae565b60408601519093506200021181620001ae565b6060959095015193969295505050565b60805160a05160c051614b28620002d660003960006104810152600081816103820152818161114e015281816112260152818161131c0152818161141d015281816114bb01528181612216015281816122ee015281816124650152818161275a01528181612b8301528181612c5b0152818161316501526136cd01526000818161032b015281816112540152818161144a0152818161231c015281816124c301528181612c8901526130500152614b286000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c8063afcb95d7116100f9578063d09dc33911610097578063e53bbc9a11610071578063e53bbc9a146104c7578063eb5dcd6c146104da578063f2fde38b146104ed578063fbffd2c11461050057600080fd5b8063d09dc339146104a3578063d57fc45a146104ab578063e3d0e712146104b457600080fd5b8063bf2732c7116100d3578063bf2732c714610438578063c10753291461044b578063c4c92b371461045e578063cc31f7dd1461047c57600080fd5b8063afcb95d7146103e8578063b121e14714610412578063b1dc65a41461042557600080fd5b806379ba5097116101665780638a1b1772116101405780638a1b17721461037d5780638ac28d5a146103a45780638da5cb5b146103b75780639c849b30146103d557600080fd5b806379ba50971461031e5780637d253aff1461032657806381ff70481461034d57600080fd5b806329937268116101a257806329937268146102415780632f7527cc146102b757806355e48749146102d15780635f27026f146102d957600080fd5b806305aeed58146101c95780630eafb25b146101dc578063181f5a7714610202575b600080fd5b6101da6101d73660046137f7565b50565b005b6101ef6101ea366004613854565b610513565b6040519081526020015b60405180910390f35b604080518082018252600f81527f565246426561636f6e20312e302e300000000000000000000000000000000000602082015290516101f991906138df565b60025460035460408051610100840467ffffffffffffffff9081168252690100000000000000000085048116602083015271010000000000000000000000000000000000909404841691810191909152918116606083015268010000000000000000900462ffffff16608082015260a0016101f9565b6102bf600881565b60405160ff90911681526020016101f9565b6101da61059f565b600e546102f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f9565b6101da61061c565b6102f97f000000000000000000000000000000000000000000000000000000000000000081565b6004546005546040805163ffffffff808516825264010000000090940490931660208401528201526060016101f9565b6102f97f000000000000000000000000000000000000000000000000000000000000000081565b6101da6103b2366004613854565b610719565b60005473ffffffffffffffffffffffffffffffffffffffff166102f9565b6101da6103e336600461393e565b610782565b6005546006546040805160008152602081019390935263ffffffff909116908201526060016101f9565b6101da610420366004613854565b6109d4565b6101da6104333660046139ec565b610acc565b6101da610446366004613c89565b610f87565b6101da610459366004613d56565b611046565b600d5473ffffffffffffffffffffffffffffffffffffffff166102f9565b6101ef7f000000000000000000000000000000000000000000000000000000000000000081565b6101ef6113e0565b6101ef600f5481565b6101da6104c2366004613db9565b611573565b6101da6104d5366004613eb8565b611dc9565b6101da6104e8366004613f29565b61201b565b6101da6104fb366004613854565b612174565b6101da61050e366004613854565b612185565b73ffffffffffffffffffffffffffffffffffffffff811660009081526007602090815260408083208151606081018352905460ff80821615158084526101008304909116948301949094526201000090046bffffffffffffffffffffffff1691810191909152906105875750600092915050565b604001516bffffffffffffffffffffffff1692915050565b600e5473ffffffffffffffffffffffffffffffffffffffff16338114610614576040517f292f4fb500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff821660248201526044015b60405180910390fd5b506000600f55565b60015473ffffffffffffffffffffffffffffffffffffffff16331461069d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161060b565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b73ffffffffffffffffffffffffffffffffffffffff8181166000908152600b6020526040902054163314610779576040517fdce38c2400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101d781612196565b61078a612569565b8281146107cd576040517f36d20459000000000000000000000000000000000000000000000000000000008152600481018490526024810182905260440161060b565b60005b838110156109cd5760008585838181106107ec576107ec613f62565b90506020020160208101906108019190613854565b9050600084848481811061081757610817613f62565b905060200201602081019061082c9190613854565b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600b602052604090205491925016801580158161089257508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b156108e9576040517febdf175600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80861660048301528316602482015260440161060b565b73ffffffffffffffffffffffffffffffffffffffff8481166000908152600b6020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016858316908117909155908316146109b6578273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f78af32efdcad432315431e9b03d27e6cd98fb79c405fdc5af7c1714d9c0f75b360405160405180910390a45b5050505080806109c590613fc0565b9150506107d0565b5050505050565b73ffffffffffffffffffffffffffffffffffffffff8181166000908152600c6020526040902054163314610a34576040517f9d12ec4f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8181166000818152600b602090815260408083208054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217909355600c909452828520805490921690915590519416939092849290917f78af32efdcad432315431e9b03d27e6cd98fb79c405fdc5af7c1714d9c0f75b39190a45050565b60005a6040805160c08101825260025460ff808216835267ffffffffffffffff61010083048116602080860191909152690100000000000000000084048216858701527101000000000000000000000000000000000090930481166060850152600354908116608085015262ffffff680100000000000000009091041660a08401523360009081526007835293909320549394509092908c01359116610ba0576040517fb1c1f68e00000000000000000000000000000000000000000000000000000000815233600482015260240161060b565b6005548b3514610bea576005546040517f93df584c00000000000000000000000000000000000000000000000000000000815260048101919091528b35602482015260440161060b565b610bf88a8a8a8a8a8a6125ec565b8151610c05906001613ff8565b60ff1687141580610c165750868514155b15610c6e578151610c28906001613ff8565b6040517ffc33647500000000000000000000000000000000000000000000000000000000815260ff9091166004820152602481018890526044810186905260640161060b565b60008a8a604051610c80929190614011565b604051908190038120610c97918e90602001614021565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012083830190925260008084529083018190529092509060005b8a811015610e885760006001858a8460208110610d0457610d04613f62565b610d1191901a601b613ff8565b8f8f86818110610d2357610d23613f62565b905060200201358e8e87818110610d3c57610d3c613f62565b9050602002013560405160008152602001604052604051610d79949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610d9b573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526008602090815290849020838501909452925460ff8082161515808552610100909204169383019390935290955092509050610e61576040517f20fb74ee00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161060b565b826020015160080260ff166001901b84019350508080610e8090613fc0565b915050610ce5565b5081827e010101010101010101010101010101010101010101010101010101010101011614610ee3576040517fc103be2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060009150819050610f328d826020020135848e8e8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061267c92505050565b600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff600888901c161790559092509050610f7884838388336128c6565b50505050505050505050505050565b600e5473ffffffffffffffffffffffffffffffffffffffff16338114610ff7576040517f292f4fb500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8216602482015260440161060b565b81516040516110099190602001614035565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120600f555050565b60005473ffffffffffffffffffffffffffffffffffffffff1633148015906111075750600d546040517f6b14daf800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690636b14daf8906110c4903390600090369060040161409a565b602060405180830381865afa1580156110e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110591906140da565b155b1561113e576040517fc04ecc2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611148612a24565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663597d2f3c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111db91906140f5565b905060006111e9828461410e565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301529192506000917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561129b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bf91906140f5565b905081811015611305576040517fcf479181000000000000000000000000000000000000000000000000000000008152600481018290526024810183905260440161060b565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663f99b1d688761135561134f8686614121565b89612b1f565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b1580156113c057600080fd5b505af11580156113d4573d6000803e3d6000fd5b50505050505050505050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116600483015260009182917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611491573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b591906140f5565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663597d2f3c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611524573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154891906140f5565b90506000611554612a24565b9050816115618285614134565b61156b9190614134565b935050505090565b888787601f8311156115bb576040517f809fc428000000000000000000000000000000000000000000000000000000008152601f60048201526024810184905260440161060b565b8183146115fe576040517f988a0804000000000000000000000000000000000000000000000000000000008152600481018490526024810183905260440161060b565b61160981600361415b565b60ff168311611650576040517ffda9db7800000000000000000000000000000000000000000000000000000000815260ff821660048201526024810184905260440161060b565b61165c8160ff16612b39565b611664612569565b60006040518060c001604052808f8f80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505081526020018d8d8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060ff8c1660208083019190915260408051601f8d0183900483028101830182528c8152920191908c908c908190840183828082843760009201919091525050509082525067ffffffffffffffff891660208083019190915260408051601f8a01839004830281018301825289815292019190899089908190840183828082843760009201919091525050509152509050611786612b73565b60095460005b8181101561187f576000600982815481106117a9576117a9613f62565b6000918252602082200154600a805473ffffffffffffffffffffffffffffffffffffffff909216935090849081106117e3576117e3613f62565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff948516835260088252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905594168252600790529190912080547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169055508061187781613fc0565b91505061178c565b5061188c6009600061373a565b611898600a600061373a565b60005b825151811015611c215760086000846000015183815181106118bf576118bf613f62565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000205460ff161561196357825180518290811061190c5761190c613f62565b60200260200101516040517f7451f83e00000000000000000000000000000000000000000000000000000000815260040161060b919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b604080518082019091526001815260ff82166020820152835180516008916000918590811061199457611994613f62565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281810192909252604001600090812083518154948401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009095169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff161761010060ff90951694909402939093179092558401518051600792919084908110611a4657611a46613f62565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000205460ff1615611aec5782602001518181518110611a9557611a95613f62565b60200260200101516040517fe8d2989900000000000000000000000000000000000000000000000000000000815260040161060b919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b60405180606001604052806001151581526020018260ff16815260200160006bffffffffffffffffffffffff168152506007600085602001518481518110611b3657611b36613f62565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040908101600020835181549385015194909201516bffffffffffffffffffffffff1662010000027fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff931515939093167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090941693909317919091179290921617905580611c1981613fc0565b91505061189b565b5081518051611c3891600991602090910190613758565b506020808301518051611c4f92600a920190613758565b506040820151600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055600454640100000000900463ffffffff16611c9f6131d5565b6004805463ffffffff928316640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff82168117909255600092611ced9281169116176001614177565b905080600460006101000a81548163ffffffff021916908363ffffffff1602179055506000611d4146308463ffffffff16886000015189602001518a604001518b606001518c608001518d60a0015161326c565b9050806005819055507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e058360055484886000015189602001518a604001518b606001518c608001518d60a00151604051611da3999897969594939291906141e5565b60405180910390a1611db58d8d613317565b505050505050505050505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314801590611e8a5750600d546040517f6b14daf800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690636b14daf890611e47903390600090369060040161409a565b602060405180830381865afa158015611e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e8891906140da565b155b15611ec1576040517fc04ecc2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ec9612b73565b6002805467ffffffffffffffff8581167101000000000000000000000000000000000081027fffffffffffffff0000000000000000ffffffffffffffffffffffffffffffffff898416690100000000000000000081027fffffffffffffffffffffffffffffff0000000000000000ffffffffffffffffff8d87166101008102919091167fffffffffffffffffffffffffffffff00000000000000000000000000000000ff909816979097171791909116919091179094556003805462ffffff87166801000000000000000081027fffffffffffffffffffffffffffffffffffffffffff00000000000000000000009092169489169485179190911790915560408051948552602085019590955293830152606082015260808101919091527f49275ddcdfc9c0519b3d094308c8bf675f06070a754ce90c152163cb6e66e8a09060a00160405180910390a15050505050565b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600b602052604090205416331461207b576040517fdce38c2400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811633036120ca576040517fb387a23800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600c6020526040902080548383167fffffffffffffffffffffffff00000000000000000000000000000000000000008216811790925590911690811461216f5760405173ffffffffffffffffffffffffffffffffffffffff8084169133918616907f84f7c7c80bb8ed2279b4aab5f61cd05e6374073d38f46d7f32de8c30e9e3836790600090a45b505050565b61217c612569565b6101d781613325565b61218d612569565b6101d78161341a565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600760209081526040918290208251606081018452905460ff80821615158084526101008304909116938301939093526201000090046bffffffffffffffffffffffff1692810192909252612205575050565b600061221083610513565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663597d2f3c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561227f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a391906140f5565b905060006122b1828461410e565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301529192506000917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015612363573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061238791906140f5565b9050818110156123cd576040517fcf479181000000000000000000000000000000000000000000000000000000008152600481018290526024810183905260440161060b565b83156125615773ffffffffffffffffffffffffffffffffffffffff8681166000908152600b602090815260408083205460079092529182902080547fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff16905590517ff99b1d680000000000000000000000000000000000000000000000000000000081529082166004820181905260248201879052917f0000000000000000000000000000000000000000000000000000000000000000169063f99b1d6890604401600060405180830381600087803b1580156124a957600080fd5b505af11580156124bd573d6000803e3d6000fd5b505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167fd0b1dac935d85bd54cf0a33b0d41d39f8cf53a968465fc7ea2377526b8ac712c8860405161255791815260200190565b60405180910390a4505b505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146125ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161060b565b565b60006125f982602061427b565b61260485602061427b565b6126108861014461410e565b61261a919061410e565b612624919061410e565b61262f90600061410e565b9050368114612673576040517ff7b94f0a0000000000000000000000000000000000000000000000000000000081526004810182905236602482015260440161060b565b50505050505050565b60008060008380602001905181019061269591906144bf565b905060006126a682606001516134c2565b90508082608001511461270957608082015160608301516040517faed0afe500000000000000000000000000000000000000000000000000000000815260048101929092526024820183905267ffffffffffffffff16604482015260640161060b565b81516020830151604080850151606086015191517f76f2e3f400000000000000000000000000000000000000000000000000000000815260009473ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016946376f2e3f4946127929492939192916004016147fa565b6020604051808303816000875af11580156127b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127d591906140da565b90508061280e576040517f69c920fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8664ffffffffff167ffc3c7a7927e878a0fca37c904953c3c75cee3ca1d1640184a0ab1c65eec6274333856020015186604001518c6040516128a5949392919073ffffffffffffffffffffffffffffffffffffffff94909416845277ffffffffffffffffffffffffffffffffffffffffffffffff92909216602084015267ffffffffffffffff166040830152606082015260800190565b60405180910390a28260200151836040015194509450505050935093915050565b60006128f23a67ffffffffffffffff8616156128e257856128e8565b87604001515b88602001516135a5565b90506010360260005a9050600061291b8663ffffffff1685858c60a0015162ffffff16866135f6565b90506000670de0b6b3a764000077ffffffffffffffffffffffffffffffffffffffffffffffff8a16830273ffffffffffffffffffffffffffffffffffffffff881660009081526007602052604090205460808d01519290910492506201000090046bffffffffffffffffffffffff9081169167ffffffffffffffff16828401019081168211156129b157505050505050506109cd565b73ffffffffffffffffffffffffffffffffffffffff8816600090815260076020526040902080546bffffffffffffffffffffffff90921662010000027fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff9092169190911790555050505050505050505050565b600080600a805480602002602001604051908101604052809291908181526020018280548015612a8a57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311612a5f575b505083519394506000925050505b81811015612b195760076000848381518110612ab657612ab6613f62565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054612b05906201000090046bffffffffffffffffffffffff168561410e565b935080612b1181613fc0565b915050612a98565b50505090565b600081831015612b30575081612b33565b50805b92915050565b806000036101d7576040517fe77dba5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612b7d612a24565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663597d2f3c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c1091906140f5565b90506000612c1e828461410e565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301529192506000917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015612cd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf491906140f5565b905081811015612d3a576040517fcf479181000000000000000000000000000000000000000000000000000000008152600481018290526024810183905260440161060b565b6000600a805480602002602001604051908101604052809291908181526020018280548015612d9f57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311612d74575b5050505050905060008151905060008167ffffffffffffffff811115612dc757612dc7613aa3565b604051908082528060200260200182016040528015612df0578160200160208202803683370190505b50905060008267ffffffffffffffff811115612e0e57612e0e613aa3565b604051908082528060200260200182016040528015612e37578160200160208202803683370190505b5090506000805b8481101561311157600060076000888481518110612e5e57612e5e613f62565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160029054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff169050600060076000898581518110612ee457612ee4613f62565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080546bffffffffffffffffffffffff9290921662010000027fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff909216919091179055808015613107576000600b60008a8681518110612f7557612f75613f62565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905080878681518110612fed57612fed613f62565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508186868151811061303a5761303a613f62565b60200260200101818152505084806001019550507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff168a86815181106130ae576130ae613f62565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fd0b1dac935d85bd54cf0a33b0d41d39f8cf53a968465fc7ea2377526b8ac712c856040516130fd91815260200190565b60405180910390a4505b5050600101612e3e565b5081518114613121578082528083525b8151156131ca576040517f73433a2f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906373433a2f9061319c908690869060040161496a565b600060405180830381600087803b1580156131b657600080fd5b505af1158015610f78573d6000803e3d6000fd5b505050505050505050565b60004661a4b18114806131ea575062066eed81145b1561326557606473ffffffffffffffffffffffffffffffffffffffff1663a3b1b31d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561323b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061325f91906140f5565b91505090565b4391505090565b6000808a8a8a8a8a8a8a8a8a604051602001613290999897969594939291906149c1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b613321828261363e565b5050565b3373ffffffffffffffffffffffffffffffffffffffff8216036133a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161060b565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600d5473ffffffffffffffffffffffffffffffffffffffff908116908216811461332157600d80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84811691821790925560408051928416835260208301919091527f793cb73064f3c8cde7e187ae515511e6e56d1ee89bf08b82fa60fb70f8d48912910160405180910390a15050565b60004661a4b18114806134d7575062066eed81145b15613595576101008367ffffffffffffffff166134f26131d5565b6134fc9190614121565b111561350b5750600092915050565b6040517f2b407a8200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152606490632b407a8290602401602060405180830381865afa15801561356a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061358e91906140f5565b9392505050565b505067ffffffffffffffff164090565b60008367ffffffffffffffff84168110156135d9576002858567ffffffffffffffff1603816135d6576135d661493b565b04015b6135ed818467ffffffffffffffff16612b1f565b95945050505050565b600081861015613632576040517f3fef97df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50909303019091010290565b610100818114613680578282826040517f418a179b00000000000000000000000000000000000000000000000000000000815260040161060b93929190614a56565b600061368e83850185614a7a565b90506040517f8eef585f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690638eef585f90613702908490600401614ae4565b600060405180830381600087803b15801561371c57600080fd5b505af1158015613730573d6000803e3d6000fd5b5050505050505050565b50805460008255906000526020600020908101906101d791906137e2565b8280548282559060005260206000209081019282156137d2579160200282015b828111156137d257825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190613778565b506137de9291506137e2565b5090565b5b808211156137de57600081556001016137e3565b60006020828403121561380957600080fd5b813567ffffffffffffffff81111561382057600080fd5b820160a0818503121561358e57600080fd5b73ffffffffffffffffffffffffffffffffffffffff811681146101d757600080fd5b60006020828403121561386657600080fd5b813561358e81613832565b60005b8381101561388c578181015183820152602001613874565b50506000910152565b600081518084526138ad816020860160208601613871565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061358e6020830184613895565b60008083601f84011261390457600080fd5b50813567ffffffffffffffff81111561391c57600080fd5b6020830191508360208260051b850101111561393757600080fd5b9250929050565b6000806000806040858703121561395457600080fd5b843567ffffffffffffffff8082111561396c57600080fd5b613978888389016138f2565b9096509450602087013591508082111561399157600080fd5b5061399e878288016138f2565b95989497509550505050565b60008083601f8401126139bc57600080fd5b50813567ffffffffffffffff8111156139d457600080fd5b60208301915083602082850101111561393757600080fd5b60008060008060008060008060e0898b031215613a0857600080fd5b606089018a811115613a1957600080fd5b8998503567ffffffffffffffff80821115613a3357600080fd5b613a3f8c838d016139aa565b909950975060808b0135915080821115613a5857600080fd5b613a648c838d016138f2565b909750955060a08b0135915080821115613a7d57600080fd5b50613a8a8b828c016138f2565b999c989b50969995989497949560c00135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613af557613af5613aa3565b60405290565b604051610100810167ffffffffffffffff81118282101715613af557613af5613aa3565b60405160a0810167ffffffffffffffff81118282101715613af557613af5613aa3565b6040516020810167ffffffffffffffff81118282101715613af557613af5613aa3565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613bac57613bac613aa3565b604052919050565b600067ffffffffffffffff821115613bce57613bce613aa3565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600067ffffffffffffffff821115613c1457613c14613aa3565b5060051b60200190565b600082601f830112613c2f57600080fd5b81356020613c44613c3f83613bfa565b613b65565b82815260059290921b84018101918181019086841115613c6357600080fd5b8286015b84811015613c7e5780358352918301918301613c67565b509695505050505050565b60006020808385031215613c9c57600080fd5b823567ffffffffffffffff80821115613cb457600080fd5b9084019060408287031215613cc857600080fd5b613cd0613ad2565b823582811115613cdf57600080fd5b8301601f81018813613cf057600080fd5b8035613cfe613c3f82613bb4565b8181528987838501011115613d1257600080fd5b818784018883013760008783830101528084525050508383013582811115613d3957600080fd5b613d4588828601613c1e565b948201949094529695505050505050565b60008060408385031215613d6957600080fd5b8235613d7481613832565b946020939093013593505050565b803560ff81168114613d9357600080fd5b919050565b67ffffffffffffffff811681146101d757600080fd5b8035613d9381613d98565b60008060008060008060008060008060c08b8d031215613dd857600080fd5b8a3567ffffffffffffffff80821115613df057600080fd5b613dfc8e838f016138f2565b909c509a5060208d0135915080821115613e1557600080fd5b613e218e838f016138f2565b909a509850889150613e3560408e01613d82565b975060608d0135915080821115613e4b57600080fd5b613e578e838f016139aa565b9097509550859150613e6b60808e01613dae565b945060a08d0135915080821115613e8157600080fd5b50613e8e8d828e016139aa565b915080935050809150509295989b9194979a5092959850565b62ffffff811681146101d757600080fd5b600080600080600060a08688031215613ed057600080fd5b8535613edb81613d98565b94506020860135613eeb81613d98565b93506040860135613efb81613d98565b92506060860135613f0b81613d98565b91506080860135613f1b81613ea7565b809150509295509295909350565b60008060408385031215613f3c57600080fd5b8235613f4781613832565b91506020830135613f5781613832565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613ff157613ff1613f91565b5060010190565b60ff8181168382160190811115612b3357612b33613f91565b8183823760009101908152919050565b828152606082602083013760800192915050565b60008251614047818460208701613871565b9190910192915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff841681526040602082015260006135ed604083018486614051565b80518015158114613d9357600080fd5b6000602082840312156140ec57600080fd5b61358e826140ca565b60006020828403121561410757600080fd5b5051919050565b80820180821115612b3357612b33613f91565b81810381811115612b3357612b33613f91565b818103600083128015838313168383128216171561415457614154613f91565b5092915050565b60ff818116838216029081169081811461415457614154613f91565b63ffffffff81811683821601908082111561415457614154613f91565b600081518084526020808501945080840160005b838110156141da57815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016141a8565b509495945050505050565b600061012063ffffffff808d1684528b6020850152808b166040850152508060608401526142158184018a614194565b905082810360808401526142298189614194565b905060ff871660a084015282810360c08401526142468187613895565b905067ffffffffffffffff851660e084015282810361010084015261426b8185613895565b9c9b505050505050505050505050565b8082028115828204841417612b3357612b33613f91565b8051613d9381613d98565b805161ffff81168114613d9357600080fd5b8051613d9381613832565b600082601f8301126142cb57600080fd5b81516142d9613c3f82613bb4565b8181528460208386010111156142ee57600080fd5b6142ff826020830160208701613871565b949350505050565b80516bffffffffffffffffffffffff81168114613d9357600080fd5b600082601f83011261433457600080fd5b81516020614344613c3f83613bfa565b82815260059290921b8401810191818101908684111561436357600080fd5b8286015b84811015613c7e57805167ffffffffffffffff8082111561438757600080fd5b908801907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06040838c03820112156143be57600080fd5b6143c6613ad2565b87840151838111156143d757600080fd5b8401610100818e03840112156143ec57600080fd5b6143f4613afb565b92508881015183526144086040820161429d565b89840152614418606082016142af565b604084015260808101518481111561442f57600080fd5b61443d8e8b838501016142ba565b60608501525061444f60a08201614307565b608084015260c081015160a084015260e081015160c084015261010081015160e08401525081815261448360408501614307565b818901528652505050918301918301614367565b805177ffffffffffffffffffffffffffffffffffffffffffffffff81168114613d9357600080fd5b6000602082840312156144d157600080fd5b815167ffffffffffffffff808211156144e957600080fd5b9083019060a082860312156144fd57600080fd5b614505613b1f565b82518281111561451457600080fd5b8301601f8101871361452557600080fd5b8051614533613c3f82613bfa565b8082825260208201915060208360051b85010192508983111561455557600080fd5b602084015b838110156146a25780518781111561457157600080fd5b850160c0818d037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00112156145a557600080fd5b6145ad613b1f565b60208201516145bb81613d98565b815260408201516145cb81613ea7565b60208201526040828e037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa001121561460257600080fd5b61460a613b42565b8d607f84011261461957600080fd5b614621613ad2565b808f60a08601111561463257600080fd5b606085015b60a08601811015614652578051835260209283019201614637565b50825250604082015260a08201518981111561466d57600080fd5b61467c8e602083860101614323565b60608301525061468e60c083016140ca565b60808201528452506020928301920161455a565b508452506146b591505060208401614497565b60208201526146c660408401614292565b60408201526146d760608401614292565b60608201526080830151608082015280935050505092915050565b600081518084526020808501808196508360051b8101915082860160005b858110156147ed57828403895281516040815181875280518288015287810151606061ffff8216818a01528383015193506080915073ffffffffffffffffffffffffffffffffffffffff8416828a01528083015193505061010060a081818b015261477f6101408b0186613895565b9284015192945060c06147a18b8201856bffffffffffffffffffffffff169052565b9084015160e08b81019190915290840151918a01919091529091015161012088015250908601516bffffffffffffffffffffffff16948601949094529784019790840190600101614710565b5091979650505050505050565b6000608080830181845280885180835260a092508286019150828160051b8701016020808c016000805b858110156148df578a85037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600187528251805167ffffffffffffffff1686528481015162ffffff16858701526040808201515160c091859089015b600282101561489e57825181529188019160019190910190880161487f565b5050506060820151818c8901526148b7828901826146f2565b928c0151801515898d01529291506148cc9050565b9785019795505091830191600101614824565b50505081965061490a8189018c77ffffffffffffffffffffffffffffffffffffffffffffffff169052565b505050505050614926604083018567ffffffffffffffff169052565b67ffffffffffffffff831660608301526135ed565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60408152600061497d6040830185614194565b82810360208481019190915284518083528582019282019060005b818110156149b457845183529383019391830191600101614998565b5090979650505050505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152614a088285018b614194565b91508382036080850152614a1c828a614194565b915060ff881660a085015283820360c0850152614a398288613895565b90861660e0850152838103610100850152905061426b8185613895565b604081526000614a6a604083018587614051565b9050826020830152949350505050565b6000610100808385031215614a8e57600080fd5b83601f840112614a9d57600080fd5b614aa5613afb565b908301908085831115614ab757600080fd5b845b83811015614ada578035614acc81613ea7565b835260209283019201614ab9565b5095945050505050565b6101008101818360005b6008811015614b1257815162ffffff16835260209283019290910190600101614aee565b5050509291505056fea164736f6c6343000813000a", +} + +var VRFBeaconABI = VRFBeaconMetaData.ABI + +var VRFBeaconBin = VRFBeaconMetaData.Bin + +func DeployVRFBeacon(auth *bind.TransactOpts, backend bind.ContractBackend, link common.Address, coordinator common.Address, keyProvider common.Address, keyID [32]byte) (common.Address, *types.Transaction, *VRFBeacon, error) { + parsed, err := VRFBeaconMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(VRFBeaconBin), backend, link, coordinator, keyProvider, keyID) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &VRFBeacon{VRFBeaconCaller: VRFBeaconCaller{contract: contract}, VRFBeaconTransactor: VRFBeaconTransactor{contract: contract}, VRFBeaconFilterer: VRFBeaconFilterer{contract: contract}}, nil +} + +type VRFBeacon struct { + address common.Address + abi abi.ABI + VRFBeaconCaller + VRFBeaconTransactor + VRFBeaconFilterer +} + +type VRFBeaconCaller struct { + contract *bind.BoundContract +} + +type VRFBeaconTransactor struct { + contract *bind.BoundContract +} + +type VRFBeaconFilterer struct { + contract *bind.BoundContract +} + +type VRFBeaconSession struct { + Contract *VRFBeacon + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type VRFBeaconCallerSession struct { + Contract *VRFBeaconCaller + CallOpts bind.CallOpts +} + +type VRFBeaconTransactorSession struct { + Contract *VRFBeaconTransactor + TransactOpts bind.TransactOpts +} + +type VRFBeaconRaw struct { + Contract *VRFBeacon +} + +type VRFBeaconCallerRaw struct { + Contract *VRFBeaconCaller +} + +type VRFBeaconTransactorRaw struct { + Contract *VRFBeaconTransactor +} + +func NewVRFBeacon(address common.Address, backend bind.ContractBackend) (*VRFBeacon, error) { + abi, err := abi.JSON(strings.NewReader(VRFBeaconABI)) + if err != nil { + return nil, err + } + contract, err := bindVRFBeacon(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &VRFBeacon{address: address, abi: abi, VRFBeaconCaller: VRFBeaconCaller{contract: contract}, VRFBeaconTransactor: VRFBeaconTransactor{contract: contract}, VRFBeaconFilterer: VRFBeaconFilterer{contract: contract}}, nil +} + +func NewVRFBeaconCaller(address common.Address, caller bind.ContractCaller) (*VRFBeaconCaller, error) { + contract, err := bindVRFBeacon(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &VRFBeaconCaller{contract: contract}, nil +} + +func NewVRFBeaconTransactor(address common.Address, transactor bind.ContractTransactor) (*VRFBeaconTransactor, error) { + contract, err := bindVRFBeacon(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &VRFBeaconTransactor{contract: contract}, nil +} + +func NewVRFBeaconFilterer(address common.Address, filterer bind.ContractFilterer) (*VRFBeaconFilterer, error) { + contract, err := bindVRFBeacon(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &VRFBeaconFilterer{contract: contract}, nil +} + +func bindVRFBeacon(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := VRFBeaconMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_VRFBeacon *VRFBeaconRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _VRFBeacon.Contract.VRFBeaconCaller.contract.Call(opts, result, method, params...) +} + +func (_VRFBeacon *VRFBeaconRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFBeacon.Contract.VRFBeaconTransactor.contract.Transfer(opts) +} + +func (_VRFBeacon *VRFBeaconRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _VRFBeacon.Contract.VRFBeaconTransactor.contract.Transact(opts, method, params...) +} + +func (_VRFBeacon *VRFBeaconCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _VRFBeacon.Contract.contract.Call(opts, result, method, params...) +} + +func (_VRFBeacon *VRFBeaconTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFBeacon.Contract.contract.Transfer(opts) +} + +func (_VRFBeacon *VRFBeaconTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _VRFBeacon.Contract.contract.Transact(opts, method, params...) +} + +func (_VRFBeacon *VRFBeaconCaller) NUMCONFDELAYS(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "NUM_CONF_DELAYS") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) NUMCONFDELAYS() (uint8, error) { + return _VRFBeacon.Contract.NUMCONFDELAYS(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) NUMCONFDELAYS() (uint8, error) { + return _VRFBeacon.Contract.NUMCONFDELAYS(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) GetBilling(opts *bind.CallOpts) (GetBilling, + + error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "getBilling") + + outstruct := new(GetBilling) + if err != nil { + return *outstruct, err + } + + outstruct.MaximumGasPrice = *abi.ConvertType(out[0], new(uint64)).(*uint64) + outstruct.ReasonableGasPrice = *abi.ConvertType(out[1], new(uint64)).(*uint64) + outstruct.ObservationPayment = *abi.ConvertType(out[2], new(uint64)).(*uint64) + outstruct.TransmissionPayment = *abi.ConvertType(out[3], new(uint64)).(*uint64) + outstruct.AccountingGas = *abi.ConvertType(out[4], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +func (_VRFBeacon *VRFBeaconSession) GetBilling() (GetBilling, + + error) { + return _VRFBeacon.Contract.GetBilling(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) GetBilling() (GetBilling, + + error) { + return _VRFBeacon.Contract.GetBilling(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) GetBillingAccessController(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "getBillingAccessController") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) GetBillingAccessController() (common.Address, error) { + return _VRFBeacon.Contract.GetBillingAccessController(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) GetBillingAccessController() (common.Address, error) { + return _VRFBeacon.Contract.GetBillingAccessController(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) ICoordinator(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "i_coordinator") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) ICoordinator() (common.Address, error) { + return _VRFBeacon.Contract.ICoordinator(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) ICoordinator() (common.Address, error) { + return _VRFBeacon.Contract.ICoordinator(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) ILink(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "i_link") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) ILink() (common.Address, error) { + return _VRFBeacon.Contract.ILink(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) ILink() (common.Address, error) { + return _VRFBeacon.Contract.ILink(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, + + error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "latestConfigDetails") + + outstruct := new(LatestConfigDetails) + if err != nil { + return *outstruct, err + } + + outstruct.ConfigCount = *abi.ConvertType(out[0], new(uint32)).(*uint32) + outstruct.BlockNumber = *abi.ConvertType(out[1], new(uint32)).(*uint32) + outstruct.ConfigDigest = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte) + + return *outstruct, err + +} + +func (_VRFBeacon *VRFBeaconSession) LatestConfigDetails() (LatestConfigDetails, + + error) { + return _VRFBeacon.Contract.LatestConfigDetails(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) LatestConfigDetails() (LatestConfigDetails, + + error) { + return _VRFBeacon.Contract.LatestConfigDetails(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, + + error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "latestConfigDigestAndEpoch") + + outstruct := new(LatestConfigDigestAndEpoch) + if err != nil { + return *outstruct, err + } + + outstruct.ScanLogs = *abi.ConvertType(out[0], new(bool)).(*bool) + outstruct.ConfigDigest = *abi.ConvertType(out[1], new([32]byte)).(*[32]byte) + outstruct.Epoch = *abi.ConvertType(out[2], new(uint32)).(*uint32) + + return *outstruct, err + +} + +func (_VRFBeacon *VRFBeaconSession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, + + error) { + return _VRFBeacon.Contract.LatestConfigDigestAndEpoch(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, + + error) { + return _VRFBeacon.Contract.LatestConfigDigestAndEpoch(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) LinkAvailableForPayment(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "linkAvailableForPayment") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) LinkAvailableForPayment() (*big.Int, error) { + return _VRFBeacon.Contract.LinkAvailableForPayment(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) LinkAvailableForPayment() (*big.Int, error) { + return _VRFBeacon.Contract.LinkAvailableForPayment(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) OwedPayment(opts *bind.CallOpts, transmitterAddress common.Address) (*big.Int, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "owedPayment", transmitterAddress) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) OwedPayment(transmitterAddress common.Address) (*big.Int, error) { + return _VRFBeacon.Contract.OwedPayment(&_VRFBeacon.CallOpts, transmitterAddress) +} + +func (_VRFBeacon *VRFBeaconCallerSession) OwedPayment(transmitterAddress common.Address) (*big.Int, error) { + return _VRFBeacon.Contract.OwedPayment(&_VRFBeacon.CallOpts, transmitterAddress) +} + +func (_VRFBeacon *VRFBeaconCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) Owner() (common.Address, error) { + return _VRFBeacon.Contract.Owner(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) Owner() (common.Address, error) { + return _VRFBeacon.Contract.Owner(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) SKeyID(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "s_keyID") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) SKeyID() ([32]byte, error) { + return _VRFBeacon.Contract.SKeyID(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) SKeyID() ([32]byte, error) { + return _VRFBeacon.Contract.SKeyID(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) SKeyProvider(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "s_keyProvider") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) SKeyProvider() (common.Address, error) { + return _VRFBeacon.Contract.SKeyProvider(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) SKeyProvider() (common.Address, error) { + return _VRFBeacon.Contract.SKeyProvider(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) SProvingKeyHash(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "s_provingKeyHash") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) SProvingKeyHash() ([32]byte, error) { + return _VRFBeacon.Contract.SProvingKeyHash(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) SProvingKeyHash() ([32]byte, error) { + return _VRFBeacon.Contract.SProvingKeyHash(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _VRFBeacon.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_VRFBeacon *VRFBeaconSession) TypeAndVersion() (string, error) { + return _VRFBeacon.Contract.TypeAndVersion(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconCallerSession) TypeAndVersion() (string, error) { + return _VRFBeacon.Contract.TypeAndVersion(&_VRFBeacon.CallOpts) +} + +func (_VRFBeacon *VRFBeaconTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "acceptOwnership") +} + +func (_VRFBeacon *VRFBeaconSession) AcceptOwnership() (*types.Transaction, error) { + return _VRFBeacon.Contract.AcceptOwnership(&_VRFBeacon.TransactOpts) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _VRFBeacon.Contract.AcceptOwnership(&_VRFBeacon.TransactOpts) +} + +func (_VRFBeacon *VRFBeaconTransactor) AcceptPayeeship(opts *bind.TransactOpts, transmitter common.Address) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "acceptPayeeship", transmitter) +} + +func (_VRFBeacon *VRFBeaconSession) AcceptPayeeship(transmitter common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.AcceptPayeeship(&_VRFBeacon.TransactOpts, transmitter) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) AcceptPayeeship(transmitter common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.AcceptPayeeship(&_VRFBeacon.TransactOpts, transmitter) +} + +func (_VRFBeacon *VRFBeaconTransactor) ExposeType(opts *bind.TransactOpts, arg0 VRFBeaconReportReport) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "exposeType", arg0) +} + +func (_VRFBeacon *VRFBeaconSession) ExposeType(arg0 VRFBeaconReportReport) (*types.Transaction, error) { + return _VRFBeacon.Contract.ExposeType(&_VRFBeacon.TransactOpts, arg0) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) ExposeType(arg0 VRFBeaconReportReport) (*types.Transaction, error) { + return _VRFBeacon.Contract.ExposeType(&_VRFBeacon.TransactOpts, arg0) +} + +func (_VRFBeacon *VRFBeaconTransactor) KeyGenerated(opts *bind.TransactOpts, kd KeyDataStructKeyData) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "keyGenerated", kd) +} + +func (_VRFBeacon *VRFBeaconSession) KeyGenerated(kd KeyDataStructKeyData) (*types.Transaction, error) { + return _VRFBeacon.Contract.KeyGenerated(&_VRFBeacon.TransactOpts, kd) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) KeyGenerated(kd KeyDataStructKeyData) (*types.Transaction, error) { + return _VRFBeacon.Contract.KeyGenerated(&_VRFBeacon.TransactOpts, kd) +} + +func (_VRFBeacon *VRFBeaconTransactor) NewKeyRequested(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "newKeyRequested") +} + +func (_VRFBeacon *VRFBeaconSession) NewKeyRequested() (*types.Transaction, error) { + return _VRFBeacon.Contract.NewKeyRequested(&_VRFBeacon.TransactOpts) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) NewKeyRequested() (*types.Transaction, error) { + return _VRFBeacon.Contract.NewKeyRequested(&_VRFBeacon.TransactOpts) +} + +func (_VRFBeacon *VRFBeaconTransactor) SetBilling(opts *bind.TransactOpts, maximumGasPrice uint64, reasonableGasPrice uint64, observationPayment uint64, transmissionPayment uint64, accountingGas *big.Int) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "setBilling", maximumGasPrice, reasonableGasPrice, observationPayment, transmissionPayment, accountingGas) +} + +func (_VRFBeacon *VRFBeaconSession) SetBilling(maximumGasPrice uint64, reasonableGasPrice uint64, observationPayment uint64, transmissionPayment uint64, accountingGas *big.Int) (*types.Transaction, error) { + return _VRFBeacon.Contract.SetBilling(&_VRFBeacon.TransactOpts, maximumGasPrice, reasonableGasPrice, observationPayment, transmissionPayment, accountingGas) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) SetBilling(maximumGasPrice uint64, reasonableGasPrice uint64, observationPayment uint64, transmissionPayment uint64, accountingGas *big.Int) (*types.Transaction, error) { + return _VRFBeacon.Contract.SetBilling(&_VRFBeacon.TransactOpts, maximumGasPrice, reasonableGasPrice, observationPayment, transmissionPayment, accountingGas) +} + +func (_VRFBeacon *VRFBeaconTransactor) SetBillingAccessController(opts *bind.TransactOpts, _billingAccessController common.Address) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "setBillingAccessController", _billingAccessController) +} + +func (_VRFBeacon *VRFBeaconSession) SetBillingAccessController(_billingAccessController common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.SetBillingAccessController(&_VRFBeacon.TransactOpts, _billingAccessController) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) SetBillingAccessController(_billingAccessController common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.SetBillingAccessController(&_VRFBeacon.TransactOpts, _billingAccessController) +} + +func (_VRFBeacon *VRFBeaconTransactor) SetConfig(opts *bind.TransactOpts, signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "setConfig", signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) +} + +func (_VRFBeacon *VRFBeaconSession) SetConfig(signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { + return _VRFBeacon.Contract.SetConfig(&_VRFBeacon.TransactOpts, signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) SetConfig(signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { + return _VRFBeacon.Contract.SetConfig(&_VRFBeacon.TransactOpts, signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) +} + +func (_VRFBeacon *VRFBeaconTransactor) SetPayees(opts *bind.TransactOpts, transmitters []common.Address, payees []common.Address) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "setPayees", transmitters, payees) +} + +func (_VRFBeacon *VRFBeaconSession) SetPayees(transmitters []common.Address, payees []common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.SetPayees(&_VRFBeacon.TransactOpts, transmitters, payees) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) SetPayees(transmitters []common.Address, payees []common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.SetPayees(&_VRFBeacon.TransactOpts, transmitters, payees) +} + +func (_VRFBeacon *VRFBeaconTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "transferOwnership", to) +} + +func (_VRFBeacon *VRFBeaconSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.TransferOwnership(&_VRFBeacon.TransactOpts, to) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.TransferOwnership(&_VRFBeacon.TransactOpts, to) +} + +func (_VRFBeacon *VRFBeaconTransactor) TransferPayeeship(opts *bind.TransactOpts, transmitter common.Address, proposed common.Address) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "transferPayeeship", transmitter, proposed) +} + +func (_VRFBeacon *VRFBeaconSession) TransferPayeeship(transmitter common.Address, proposed common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.TransferPayeeship(&_VRFBeacon.TransactOpts, transmitter, proposed) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) TransferPayeeship(transmitter common.Address, proposed common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.TransferPayeeship(&_VRFBeacon.TransactOpts, transmitter, proposed) +} + +func (_VRFBeacon *VRFBeaconTransactor) Transmit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "transmit", reportContext, report, rs, ss, rawVs) +} + +func (_VRFBeacon *VRFBeaconSession) Transmit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { + return _VRFBeacon.Contract.Transmit(&_VRFBeacon.TransactOpts, reportContext, report, rs, ss, rawVs) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) Transmit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { + return _VRFBeacon.Contract.Transmit(&_VRFBeacon.TransactOpts, reportContext, report, rs, ss, rawVs) +} + +func (_VRFBeacon *VRFBeaconTransactor) WithdrawFunds(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "withdrawFunds", recipient, amount) +} + +func (_VRFBeacon *VRFBeaconSession) WithdrawFunds(recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _VRFBeacon.Contract.WithdrawFunds(&_VRFBeacon.TransactOpts, recipient, amount) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) WithdrawFunds(recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _VRFBeacon.Contract.WithdrawFunds(&_VRFBeacon.TransactOpts, recipient, amount) +} + +func (_VRFBeacon *VRFBeaconTransactor) WithdrawPayment(opts *bind.TransactOpts, transmitter common.Address) (*types.Transaction, error) { + return _VRFBeacon.contract.Transact(opts, "withdrawPayment", transmitter) +} + +func (_VRFBeacon *VRFBeaconSession) WithdrawPayment(transmitter common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.WithdrawPayment(&_VRFBeacon.TransactOpts, transmitter) +} + +func (_VRFBeacon *VRFBeaconTransactorSession) WithdrawPayment(transmitter common.Address) (*types.Transaction, error) { + return _VRFBeacon.Contract.WithdrawPayment(&_VRFBeacon.TransactOpts, transmitter) +} + +type VRFBeaconBillingAccessControllerSetIterator struct { + Event *VRFBeaconBillingAccessControllerSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconBillingAccessControllerSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconBillingAccessControllerSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconBillingAccessControllerSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconBillingAccessControllerSetIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconBillingAccessControllerSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconBillingAccessControllerSet struct { + Old common.Address + Current common.Address + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterBillingAccessControllerSet(opts *bind.FilterOpts) (*VRFBeaconBillingAccessControllerSetIterator, error) { + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "BillingAccessControllerSet") + if err != nil { + return nil, err + } + return &VRFBeaconBillingAccessControllerSetIterator{contract: _VRFBeacon.contract, event: "BillingAccessControllerSet", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchBillingAccessControllerSet(opts *bind.WatchOpts, sink chan<- *VRFBeaconBillingAccessControllerSet) (event.Subscription, error) { + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "BillingAccessControllerSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconBillingAccessControllerSet) + if err := _VRFBeacon.contract.UnpackLog(event, "BillingAccessControllerSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseBillingAccessControllerSet(log types.Log) (*VRFBeaconBillingAccessControllerSet, error) { + event := new(VRFBeaconBillingAccessControllerSet) + if err := _VRFBeacon.contract.UnpackLog(event, "BillingAccessControllerSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconBillingSetIterator struct { + Event *VRFBeaconBillingSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconBillingSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconBillingSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconBillingSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconBillingSetIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconBillingSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconBillingSet struct { + MaximumGasPrice uint64 + ReasonableGasPrice uint64 + ObservationPayment uint64 + TransmissionPayment uint64 + AccountingGas *big.Int + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterBillingSet(opts *bind.FilterOpts) (*VRFBeaconBillingSetIterator, error) { + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "BillingSet") + if err != nil { + return nil, err + } + return &VRFBeaconBillingSetIterator{contract: _VRFBeacon.contract, event: "BillingSet", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchBillingSet(opts *bind.WatchOpts, sink chan<- *VRFBeaconBillingSet) (event.Subscription, error) { + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "BillingSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconBillingSet) + if err := _VRFBeacon.contract.UnpackLog(event, "BillingSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseBillingSet(log types.Log) (*VRFBeaconBillingSet, error) { + event := new(VRFBeaconBillingSet) + if err := _VRFBeacon.contract.UnpackLog(event, "BillingSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconConfigSetIterator struct { + Event *VRFBeaconConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconConfigSetIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconConfigSet struct { + PreviousConfigBlockNumber uint32 + ConfigDigest [32]byte + ConfigCount uint64 + Signers []common.Address + Transmitters []common.Address + F uint8 + OnchainConfig []byte + OffchainConfigVersion uint64 + OffchainConfig []byte + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterConfigSet(opts *bind.FilterOpts) (*VRFBeaconConfigSetIterator, error) { + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "ConfigSet") + if err != nil { + return nil, err + } + return &VRFBeaconConfigSetIterator{contract: _VRFBeacon.contract, event: "ConfigSet", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *VRFBeaconConfigSet) (event.Subscription, error) { + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "ConfigSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconConfigSet) + if err := _VRFBeacon.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseConfigSet(log types.Log) (*VRFBeaconConfigSet, error) { + event := new(VRFBeaconConfigSet) + if err := _VRFBeacon.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconNewTransmissionIterator struct { + Event *VRFBeaconNewTransmission + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconNewTransmissionIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconNewTransmission) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconNewTransmission) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconNewTransmissionIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconNewTransmissionIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconNewTransmission struct { + EpochAndRound *big.Int + Transmitter common.Address + JuelsPerFeeCoin *big.Int + ReasonableGasPrice uint64 + ConfigDigest [32]byte + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterNewTransmission(opts *bind.FilterOpts, epochAndRound []*big.Int) (*VRFBeaconNewTransmissionIterator, error) { + + var epochAndRoundRule []interface{} + for _, epochAndRoundItem := range epochAndRound { + epochAndRoundRule = append(epochAndRoundRule, epochAndRoundItem) + } + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "NewTransmission", epochAndRoundRule) + if err != nil { + return nil, err + } + return &VRFBeaconNewTransmissionIterator{contract: _VRFBeacon.contract, event: "NewTransmission", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchNewTransmission(opts *bind.WatchOpts, sink chan<- *VRFBeaconNewTransmission, epochAndRound []*big.Int) (event.Subscription, error) { + + var epochAndRoundRule []interface{} + for _, epochAndRoundItem := range epochAndRound { + epochAndRoundRule = append(epochAndRoundRule, epochAndRoundItem) + } + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "NewTransmission", epochAndRoundRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconNewTransmission) + if err := _VRFBeacon.contract.UnpackLog(event, "NewTransmission", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseNewTransmission(log types.Log) (*VRFBeaconNewTransmission, error) { + event := new(VRFBeaconNewTransmission) + if err := _VRFBeacon.contract.UnpackLog(event, "NewTransmission", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconOraclePaidIterator struct { + Event *VRFBeaconOraclePaid + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconOraclePaidIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconOraclePaid) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconOraclePaid) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconOraclePaidIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconOraclePaidIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconOraclePaid struct { + Transmitter common.Address + Payee common.Address + Amount *big.Int + LinkToken common.Address + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterOraclePaid(opts *bind.FilterOpts, transmitter []common.Address, payee []common.Address, linkToken []common.Address) (*VRFBeaconOraclePaidIterator, error) { + + var transmitterRule []interface{} + for _, transmitterItem := range transmitter { + transmitterRule = append(transmitterRule, transmitterItem) + } + var payeeRule []interface{} + for _, payeeItem := range payee { + payeeRule = append(payeeRule, payeeItem) + } + + var linkTokenRule []interface{} + for _, linkTokenItem := range linkToken { + linkTokenRule = append(linkTokenRule, linkTokenItem) + } + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "OraclePaid", transmitterRule, payeeRule, linkTokenRule) + if err != nil { + return nil, err + } + return &VRFBeaconOraclePaidIterator{contract: _VRFBeacon.contract, event: "OraclePaid", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchOraclePaid(opts *bind.WatchOpts, sink chan<- *VRFBeaconOraclePaid, transmitter []common.Address, payee []common.Address, linkToken []common.Address) (event.Subscription, error) { + + var transmitterRule []interface{} + for _, transmitterItem := range transmitter { + transmitterRule = append(transmitterRule, transmitterItem) + } + var payeeRule []interface{} + for _, payeeItem := range payee { + payeeRule = append(payeeRule, payeeItem) + } + + var linkTokenRule []interface{} + for _, linkTokenItem := range linkToken { + linkTokenRule = append(linkTokenRule, linkTokenItem) + } + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "OraclePaid", transmitterRule, payeeRule, linkTokenRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconOraclePaid) + if err := _VRFBeacon.contract.UnpackLog(event, "OraclePaid", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseOraclePaid(log types.Log) (*VRFBeaconOraclePaid, error) { + event := new(VRFBeaconOraclePaid) + if err := _VRFBeacon.contract.UnpackLog(event, "OraclePaid", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconOutputsServedIterator struct { + Event *VRFBeaconOutputsServed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconOutputsServedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconOutputsServed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconOutputsServed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconOutputsServedIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconOutputsServedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconOutputsServed struct { + RecentBlockHeight uint64 + JuelsPerFeeCoin *big.Int + ReasonableGasPrice uint64 + OutputsServed []VRFBeaconTypesOutputServed + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterOutputsServed(opts *bind.FilterOpts) (*VRFBeaconOutputsServedIterator, error) { + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "OutputsServed") + if err != nil { + return nil, err + } + return &VRFBeaconOutputsServedIterator{contract: _VRFBeacon.contract, event: "OutputsServed", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchOutputsServed(opts *bind.WatchOpts, sink chan<- *VRFBeaconOutputsServed) (event.Subscription, error) { + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "OutputsServed") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconOutputsServed) + if err := _VRFBeacon.contract.UnpackLog(event, "OutputsServed", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseOutputsServed(log types.Log) (*VRFBeaconOutputsServed, error) { + event := new(VRFBeaconOutputsServed) + if err := _VRFBeacon.contract.UnpackLog(event, "OutputsServed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconOwnershipTransferRequestedIterator struct { + Event *VRFBeaconOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFBeaconOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &VRFBeaconOwnershipTransferRequestedIterator{contract: _VRFBeacon.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFBeaconOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconOwnershipTransferRequested) + if err := _VRFBeacon.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseOwnershipTransferRequested(log types.Log) (*VRFBeaconOwnershipTransferRequested, error) { + event := new(VRFBeaconOwnershipTransferRequested) + if err := _VRFBeacon.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconOwnershipTransferredIterator struct { + Event *VRFBeaconOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFBeaconOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &VRFBeaconOwnershipTransferredIterator{contract: _VRFBeacon.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *VRFBeaconOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconOwnershipTransferred) + if err := _VRFBeacon.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseOwnershipTransferred(log types.Log) (*VRFBeaconOwnershipTransferred, error) { + event := new(VRFBeaconOwnershipTransferred) + if err := _VRFBeacon.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconPayeeshipTransferRequestedIterator struct { + Event *VRFBeaconPayeeshipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconPayeeshipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconPayeeshipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconPayeeshipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconPayeeshipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconPayeeshipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconPayeeshipTransferRequested struct { + Transmitter common.Address + Current common.Address + Proposed common.Address + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterPayeeshipTransferRequested(opts *bind.FilterOpts, transmitter []common.Address, current []common.Address, proposed []common.Address) (*VRFBeaconPayeeshipTransferRequestedIterator, error) { + + var transmitterRule []interface{} + for _, transmitterItem := range transmitter { + transmitterRule = append(transmitterRule, transmitterItem) + } + var currentRule []interface{} + for _, currentItem := range current { + currentRule = append(currentRule, currentItem) + } + var proposedRule []interface{} + for _, proposedItem := range proposed { + proposedRule = append(proposedRule, proposedItem) + } + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "PayeeshipTransferRequested", transmitterRule, currentRule, proposedRule) + if err != nil { + return nil, err + } + return &VRFBeaconPayeeshipTransferRequestedIterator{contract: _VRFBeacon.contract, event: "PayeeshipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchPayeeshipTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFBeaconPayeeshipTransferRequested, transmitter []common.Address, current []common.Address, proposed []common.Address) (event.Subscription, error) { + + var transmitterRule []interface{} + for _, transmitterItem := range transmitter { + transmitterRule = append(transmitterRule, transmitterItem) + } + var currentRule []interface{} + for _, currentItem := range current { + currentRule = append(currentRule, currentItem) + } + var proposedRule []interface{} + for _, proposedItem := range proposed { + proposedRule = append(proposedRule, proposedItem) + } + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "PayeeshipTransferRequested", transmitterRule, currentRule, proposedRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconPayeeshipTransferRequested) + if err := _VRFBeacon.contract.UnpackLog(event, "PayeeshipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParsePayeeshipTransferRequested(log types.Log) (*VRFBeaconPayeeshipTransferRequested, error) { + event := new(VRFBeaconPayeeshipTransferRequested) + if err := _VRFBeacon.contract.UnpackLog(event, "PayeeshipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconPayeeshipTransferredIterator struct { + Event *VRFBeaconPayeeshipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconPayeeshipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconPayeeshipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconPayeeshipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconPayeeshipTransferredIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconPayeeshipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconPayeeshipTransferred struct { + Transmitter common.Address + Previous common.Address + Current common.Address + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterPayeeshipTransferred(opts *bind.FilterOpts, transmitter []common.Address, previous []common.Address, current []common.Address) (*VRFBeaconPayeeshipTransferredIterator, error) { + + var transmitterRule []interface{} + for _, transmitterItem := range transmitter { + transmitterRule = append(transmitterRule, transmitterItem) + } + var previousRule []interface{} + for _, previousItem := range previous { + previousRule = append(previousRule, previousItem) + } + var currentRule []interface{} + for _, currentItem := range current { + currentRule = append(currentRule, currentItem) + } + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "PayeeshipTransferred", transmitterRule, previousRule, currentRule) + if err != nil { + return nil, err + } + return &VRFBeaconPayeeshipTransferredIterator{contract: _VRFBeacon.contract, event: "PayeeshipTransferred", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchPayeeshipTransferred(opts *bind.WatchOpts, sink chan<- *VRFBeaconPayeeshipTransferred, transmitter []common.Address, previous []common.Address, current []common.Address) (event.Subscription, error) { + + var transmitterRule []interface{} + for _, transmitterItem := range transmitter { + transmitterRule = append(transmitterRule, transmitterItem) + } + var previousRule []interface{} + for _, previousItem := range previous { + previousRule = append(previousRule, previousItem) + } + var currentRule []interface{} + for _, currentItem := range current { + currentRule = append(currentRule, currentItem) + } + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "PayeeshipTransferred", transmitterRule, previousRule, currentRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconPayeeshipTransferred) + if err := _VRFBeacon.contract.UnpackLog(event, "PayeeshipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParsePayeeshipTransferred(log types.Log) (*VRFBeaconPayeeshipTransferred, error) { + event := new(VRFBeaconPayeeshipTransferred) + if err := _VRFBeacon.contract.UnpackLog(event, "PayeeshipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconRandomWordsFulfilledIterator struct { + Event *VRFBeaconRandomWordsFulfilled + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconRandomWordsFulfilledIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconRandomWordsFulfilled) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconRandomWordsFulfilled) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconRandomWordsFulfilledIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconRandomWordsFulfilledIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconRandomWordsFulfilled struct { + RequestIDs []*big.Int + SuccessfulFulfillment []byte + TruncatedErrorData [][]byte + SubBalances []*big.Int + SubIDs []*big.Int + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterRandomWordsFulfilled(opts *bind.FilterOpts) (*VRFBeaconRandomWordsFulfilledIterator, error) { + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "RandomWordsFulfilled") + if err != nil { + return nil, err + } + return &VRFBeaconRandomWordsFulfilledIterator{contract: _VRFBeacon.contract, event: "RandomWordsFulfilled", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchRandomWordsFulfilled(opts *bind.WatchOpts, sink chan<- *VRFBeaconRandomWordsFulfilled) (event.Subscription, error) { + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "RandomWordsFulfilled") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconRandomWordsFulfilled) + if err := _VRFBeacon.contract.UnpackLog(event, "RandomWordsFulfilled", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseRandomWordsFulfilled(log types.Log) (*VRFBeaconRandomWordsFulfilled, error) { + event := new(VRFBeaconRandomWordsFulfilled) + if err := _VRFBeacon.contract.UnpackLog(event, "RandomWordsFulfilled", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconRandomnessFulfillmentRequestedIterator struct { + Event *VRFBeaconRandomnessFulfillmentRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconRandomnessFulfillmentRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconRandomnessFulfillmentRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconRandomnessFulfillmentRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconRandomnessFulfillmentRequestedIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconRandomnessFulfillmentRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconRandomnessFulfillmentRequested struct { + RequestID *big.Int + Requester common.Address + NextBeaconOutputHeight uint64 + ConfDelay *big.Int + SubID *big.Int + NumWords uint16 + GasAllowance uint32 + GasPrice *big.Int + WeiPerUnitLink *big.Int + Arguments []byte + CostJuels *big.Int + NewSubBalance *big.Int + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterRandomnessFulfillmentRequested(opts *bind.FilterOpts, requestID []*big.Int) (*VRFBeaconRandomnessFulfillmentRequestedIterator, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "RandomnessFulfillmentRequested", requestIDRule) + if err != nil { + return nil, err + } + return &VRFBeaconRandomnessFulfillmentRequestedIterator{contract: _VRFBeacon.contract, event: "RandomnessFulfillmentRequested", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchRandomnessFulfillmentRequested(opts *bind.WatchOpts, sink chan<- *VRFBeaconRandomnessFulfillmentRequested, requestID []*big.Int) (event.Subscription, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "RandomnessFulfillmentRequested", requestIDRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconRandomnessFulfillmentRequested) + if err := _VRFBeacon.contract.UnpackLog(event, "RandomnessFulfillmentRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseRandomnessFulfillmentRequested(log types.Log) (*VRFBeaconRandomnessFulfillmentRequested, error) { + event := new(VRFBeaconRandomnessFulfillmentRequested) + if err := _VRFBeacon.contract.UnpackLog(event, "RandomnessFulfillmentRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconRandomnessRedeemedIterator struct { + Event *VRFBeaconRandomnessRedeemed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconRandomnessRedeemedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconRandomnessRedeemed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconRandomnessRedeemed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconRandomnessRedeemedIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconRandomnessRedeemedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconRandomnessRedeemed struct { + RequestID *big.Int + Requester common.Address + SubID *big.Int + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterRandomnessRedeemed(opts *bind.FilterOpts, requestID []*big.Int, requester []common.Address) (*VRFBeaconRandomnessRedeemedIterator, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + var requesterRule []interface{} + for _, requesterItem := range requester { + requesterRule = append(requesterRule, requesterItem) + } + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "RandomnessRedeemed", requestIDRule, requesterRule) + if err != nil { + return nil, err + } + return &VRFBeaconRandomnessRedeemedIterator{contract: _VRFBeacon.contract, event: "RandomnessRedeemed", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchRandomnessRedeemed(opts *bind.WatchOpts, sink chan<- *VRFBeaconRandomnessRedeemed, requestID []*big.Int, requester []common.Address) (event.Subscription, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + var requesterRule []interface{} + for _, requesterItem := range requester { + requesterRule = append(requesterRule, requesterItem) + } + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "RandomnessRedeemed", requestIDRule, requesterRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconRandomnessRedeemed) + if err := _VRFBeacon.contract.UnpackLog(event, "RandomnessRedeemed", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseRandomnessRedeemed(log types.Log) (*VRFBeaconRandomnessRedeemed, error) { + event := new(VRFBeaconRandomnessRedeemed) + if err := _VRFBeacon.contract.UnpackLog(event, "RandomnessRedeemed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFBeaconRandomnessRequestedIterator struct { + Event *VRFBeaconRandomnessRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFBeaconRandomnessRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFBeaconRandomnessRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFBeaconRandomnessRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFBeaconRandomnessRequestedIterator) Error() error { + return it.fail +} + +func (it *VRFBeaconRandomnessRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFBeaconRandomnessRequested struct { + RequestID *big.Int + Requester common.Address + NextBeaconOutputHeight uint64 + ConfDelay *big.Int + SubID *big.Int + NumWords uint16 + CostJuels *big.Int + NewSubBalance *big.Int + Raw types.Log +} + +func (_VRFBeacon *VRFBeaconFilterer) FilterRandomnessRequested(opts *bind.FilterOpts, requestID []*big.Int) (*VRFBeaconRandomnessRequestedIterator, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + + logs, sub, err := _VRFBeacon.contract.FilterLogs(opts, "RandomnessRequested", requestIDRule) + if err != nil { + return nil, err + } + return &VRFBeaconRandomnessRequestedIterator{contract: _VRFBeacon.contract, event: "RandomnessRequested", logs: logs, sub: sub}, nil +} + +func (_VRFBeacon *VRFBeaconFilterer) WatchRandomnessRequested(opts *bind.WatchOpts, sink chan<- *VRFBeaconRandomnessRequested, requestID []*big.Int) (event.Subscription, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + + logs, sub, err := _VRFBeacon.contract.WatchLogs(opts, "RandomnessRequested", requestIDRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFBeaconRandomnessRequested) + if err := _VRFBeacon.contract.UnpackLog(event, "RandomnessRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFBeacon *VRFBeaconFilterer) ParseRandomnessRequested(log types.Log) (*VRFBeaconRandomnessRequested, error) { + event := new(VRFBeaconRandomnessRequested) + if err := _VRFBeacon.contract.UnpackLog(event, "RandomnessRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type GetBilling struct { + MaximumGasPrice uint64 + ReasonableGasPrice uint64 + ObservationPayment uint64 + TransmissionPayment uint64 + AccountingGas *big.Int +} +type LatestConfigDetails struct { + ConfigCount uint32 + BlockNumber uint32 + ConfigDigest [32]byte +} +type LatestConfigDigestAndEpoch struct { + ScanLogs bool + ConfigDigest [32]byte + Epoch uint32 +} + +func (_VRFBeacon *VRFBeacon) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _VRFBeacon.abi.Events["BillingAccessControllerSet"].ID: + return _VRFBeacon.ParseBillingAccessControllerSet(log) + case _VRFBeacon.abi.Events["BillingSet"].ID: + return _VRFBeacon.ParseBillingSet(log) + case _VRFBeacon.abi.Events["ConfigSet"].ID: + return _VRFBeacon.ParseConfigSet(log) + case _VRFBeacon.abi.Events["NewTransmission"].ID: + return _VRFBeacon.ParseNewTransmission(log) + case _VRFBeacon.abi.Events["OraclePaid"].ID: + return _VRFBeacon.ParseOraclePaid(log) + case _VRFBeacon.abi.Events["OutputsServed"].ID: + return _VRFBeacon.ParseOutputsServed(log) + case _VRFBeacon.abi.Events["OwnershipTransferRequested"].ID: + return _VRFBeacon.ParseOwnershipTransferRequested(log) + case _VRFBeacon.abi.Events["OwnershipTransferred"].ID: + return _VRFBeacon.ParseOwnershipTransferred(log) + case _VRFBeacon.abi.Events["PayeeshipTransferRequested"].ID: + return _VRFBeacon.ParsePayeeshipTransferRequested(log) + case _VRFBeacon.abi.Events["PayeeshipTransferred"].ID: + return _VRFBeacon.ParsePayeeshipTransferred(log) + case _VRFBeacon.abi.Events["RandomWordsFulfilled"].ID: + return _VRFBeacon.ParseRandomWordsFulfilled(log) + case _VRFBeacon.abi.Events["RandomnessFulfillmentRequested"].ID: + return _VRFBeacon.ParseRandomnessFulfillmentRequested(log) + case _VRFBeacon.abi.Events["RandomnessRedeemed"].ID: + return _VRFBeacon.ParseRandomnessRedeemed(log) + case _VRFBeacon.abi.Events["RandomnessRequested"].ID: + return _VRFBeacon.ParseRandomnessRequested(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (VRFBeaconBillingAccessControllerSet) Topic() common.Hash { + return common.HexToHash("0x793cb73064f3c8cde7e187ae515511e6e56d1ee89bf08b82fa60fb70f8d48912") +} + +func (VRFBeaconBillingSet) Topic() common.Hash { + return common.HexToHash("0x49275ddcdfc9c0519b3d094308c8bf675f06070a754ce90c152163cb6e66e8a0") +} + +func (VRFBeaconConfigSet) Topic() common.Hash { + return common.HexToHash("0x1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05") +} + +func (VRFBeaconNewTransmission) Topic() common.Hash { + return common.HexToHash("0xfc3c7a7927e878a0fca37c904953c3c75cee3ca1d1640184a0ab1c65eec62743") +} + +func (VRFBeaconOraclePaid) Topic() common.Hash { + return common.HexToHash("0xd0b1dac935d85bd54cf0a33b0d41d39f8cf53a968465fc7ea2377526b8ac712c") +} + +func (VRFBeaconOutputsServed) Topic() common.Hash { + return common.HexToHash("0xf10ea936d00579b4c52035ee33bf46929646b3aa87554c565d8fb2c7aa549c44") +} + +func (VRFBeaconOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (VRFBeaconOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (VRFBeaconPayeeshipTransferRequested) Topic() common.Hash { + return common.HexToHash("0x84f7c7c80bb8ed2279b4aab5f61cd05e6374073d38f46d7f32de8c30e9e38367") +} + +func (VRFBeaconPayeeshipTransferred) Topic() common.Hash { + return common.HexToHash("0x78af32efdcad432315431e9b03d27e6cd98fb79c405fdc5af7c1714d9c0f75b3") +} + +func (VRFBeaconRandomWordsFulfilled) Topic() common.Hash { + return common.HexToHash("0x8f79f730779e875ce76c428039cc2052b5b5918c2a55c598fab251c1198aec54") +} + +func (VRFBeaconRandomnessFulfillmentRequested) Topic() common.Hash { + return common.HexToHash("0x01872fb9c7d6d68af06a17347935e04412da302a377224c205e672c26e18c37f") +} + +func (VRFBeaconRandomnessRedeemed) Topic() common.Hash { + return common.HexToHash("0x16f3f633197fafab10a5df69e6f3f2f7f20092f08d8d47de0a91c0f4b96a1a25") +} + +func (VRFBeaconRandomnessRequested) Topic() common.Hash { + return common.HexToHash("0xb7933fba96b6b452eb44f99fdc08052a45dff82363d59abaff0456931c3d2459") +} + +func (_VRFBeacon *VRFBeacon) Address() common.Address { + return _VRFBeacon.address +} + +type VRFBeaconInterface interface { + NUMCONFDELAYS(opts *bind.CallOpts) (uint8, error) + + GetBilling(opts *bind.CallOpts) (GetBilling, + + error) + + GetBillingAccessController(opts *bind.CallOpts) (common.Address, error) + + ICoordinator(opts *bind.CallOpts) (common.Address, error) + + ILink(opts *bind.CallOpts) (common.Address, error) + + LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, + + error) + + LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, + + error) + + LinkAvailableForPayment(opts *bind.CallOpts) (*big.Int, error) + + OwedPayment(opts *bind.CallOpts, transmitterAddress common.Address) (*big.Int, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + SKeyID(opts *bind.CallOpts) ([32]byte, error) + + SKeyProvider(opts *bind.CallOpts) (common.Address, error) + + SProvingKeyHash(opts *bind.CallOpts) ([32]byte, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + AcceptPayeeship(opts *bind.TransactOpts, transmitter common.Address) (*types.Transaction, error) + + ExposeType(opts *bind.TransactOpts, arg0 VRFBeaconReportReport) (*types.Transaction, error) + + KeyGenerated(opts *bind.TransactOpts, kd KeyDataStructKeyData) (*types.Transaction, error) + + NewKeyRequested(opts *bind.TransactOpts) (*types.Transaction, error) + + SetBilling(opts *bind.TransactOpts, maximumGasPrice uint64, reasonableGasPrice uint64, observationPayment uint64, transmissionPayment uint64, accountingGas *big.Int) (*types.Transaction, error) + + SetBillingAccessController(opts *bind.TransactOpts, _billingAccessController common.Address) (*types.Transaction, error) + + SetConfig(opts *bind.TransactOpts, signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) + + SetPayees(opts *bind.TransactOpts, transmitters []common.Address, payees []common.Address) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + TransferPayeeship(opts *bind.TransactOpts, transmitter common.Address, proposed common.Address) (*types.Transaction, error) + + Transmit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) + + WithdrawFunds(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) + + WithdrawPayment(opts *bind.TransactOpts, transmitter common.Address) (*types.Transaction, error) + + FilterBillingAccessControllerSet(opts *bind.FilterOpts) (*VRFBeaconBillingAccessControllerSetIterator, error) + + WatchBillingAccessControllerSet(opts *bind.WatchOpts, sink chan<- *VRFBeaconBillingAccessControllerSet) (event.Subscription, error) + + ParseBillingAccessControllerSet(log types.Log) (*VRFBeaconBillingAccessControllerSet, error) + + FilterBillingSet(opts *bind.FilterOpts) (*VRFBeaconBillingSetIterator, error) + + WatchBillingSet(opts *bind.WatchOpts, sink chan<- *VRFBeaconBillingSet) (event.Subscription, error) + + ParseBillingSet(log types.Log) (*VRFBeaconBillingSet, error) + + FilterConfigSet(opts *bind.FilterOpts) (*VRFBeaconConfigSetIterator, error) + + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *VRFBeaconConfigSet) (event.Subscription, error) + + ParseConfigSet(log types.Log) (*VRFBeaconConfigSet, error) + + FilterNewTransmission(opts *bind.FilterOpts, epochAndRound []*big.Int) (*VRFBeaconNewTransmissionIterator, error) + + WatchNewTransmission(opts *bind.WatchOpts, sink chan<- *VRFBeaconNewTransmission, epochAndRound []*big.Int) (event.Subscription, error) + + ParseNewTransmission(log types.Log) (*VRFBeaconNewTransmission, error) + + FilterOraclePaid(opts *bind.FilterOpts, transmitter []common.Address, payee []common.Address, linkToken []common.Address) (*VRFBeaconOraclePaidIterator, error) + + WatchOraclePaid(opts *bind.WatchOpts, sink chan<- *VRFBeaconOraclePaid, transmitter []common.Address, payee []common.Address, linkToken []common.Address) (event.Subscription, error) + + ParseOraclePaid(log types.Log) (*VRFBeaconOraclePaid, error) + + FilterOutputsServed(opts *bind.FilterOpts) (*VRFBeaconOutputsServedIterator, error) + + WatchOutputsServed(opts *bind.WatchOpts, sink chan<- *VRFBeaconOutputsServed) (event.Subscription, error) + + ParseOutputsServed(log types.Log) (*VRFBeaconOutputsServed, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFBeaconOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFBeaconOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*VRFBeaconOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFBeaconOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *VRFBeaconOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*VRFBeaconOwnershipTransferred, error) + + FilterPayeeshipTransferRequested(opts *bind.FilterOpts, transmitter []common.Address, current []common.Address, proposed []common.Address) (*VRFBeaconPayeeshipTransferRequestedIterator, error) + + WatchPayeeshipTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFBeaconPayeeshipTransferRequested, transmitter []common.Address, current []common.Address, proposed []common.Address) (event.Subscription, error) + + ParsePayeeshipTransferRequested(log types.Log) (*VRFBeaconPayeeshipTransferRequested, error) + + FilterPayeeshipTransferred(opts *bind.FilterOpts, transmitter []common.Address, previous []common.Address, current []common.Address) (*VRFBeaconPayeeshipTransferredIterator, error) + + WatchPayeeshipTransferred(opts *bind.WatchOpts, sink chan<- *VRFBeaconPayeeshipTransferred, transmitter []common.Address, previous []common.Address, current []common.Address) (event.Subscription, error) + + ParsePayeeshipTransferred(log types.Log) (*VRFBeaconPayeeshipTransferred, error) + + FilterRandomWordsFulfilled(opts *bind.FilterOpts) (*VRFBeaconRandomWordsFulfilledIterator, error) + + WatchRandomWordsFulfilled(opts *bind.WatchOpts, sink chan<- *VRFBeaconRandomWordsFulfilled) (event.Subscription, error) + + ParseRandomWordsFulfilled(log types.Log) (*VRFBeaconRandomWordsFulfilled, error) + + FilterRandomnessFulfillmentRequested(opts *bind.FilterOpts, requestID []*big.Int) (*VRFBeaconRandomnessFulfillmentRequestedIterator, error) + + WatchRandomnessFulfillmentRequested(opts *bind.WatchOpts, sink chan<- *VRFBeaconRandomnessFulfillmentRequested, requestID []*big.Int) (event.Subscription, error) + + ParseRandomnessFulfillmentRequested(log types.Log) (*VRFBeaconRandomnessFulfillmentRequested, error) + + FilterRandomnessRedeemed(opts *bind.FilterOpts, requestID []*big.Int, requester []common.Address) (*VRFBeaconRandomnessRedeemedIterator, error) + + WatchRandomnessRedeemed(opts *bind.WatchOpts, sink chan<- *VRFBeaconRandomnessRedeemed, requestID []*big.Int, requester []common.Address) (event.Subscription, error) + + ParseRandomnessRedeemed(log types.Log) (*VRFBeaconRandomnessRedeemed, error) + + FilterRandomnessRequested(opts *bind.FilterOpts, requestID []*big.Int) (*VRFBeaconRandomnessRequestedIterator, error) + + WatchRandomnessRequested(opts *bind.WatchOpts, sink chan<- *VRFBeaconRandomnessRequested, requestID []*big.Int) (event.Subscription, error) + + ParseRandomnessRequested(log types.Log) (*VRFBeaconRandomnessRequested, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ocr2vrf/generated/vrf_beacon_consumer/vrf_beacon_consumer.go b/core/gethwrappers/ocr2vrf/generated/vrf_beacon_consumer/vrf_beacon_consumer.go new file mode 100644 index 00000000000..edc4ec6556d --- /dev/null +++ b/core/gethwrappers/ocr2vrf/generated/vrf_beacon_consumer/vrf_beacon_consumer.go @@ -0,0 +1,1034 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package vrf_beacon_consumer + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var BeaconVRFConsumerMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"shouldFail\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"beaconPeriodBlocks\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"MustBeCoordinator\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeOwnerOrCoordinator\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"}],\"name\":\"CoordinatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fail\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_beaconPeriodBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"randomWords\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"}],\"name\":\"rawFulfillRandomWords\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_ReceivedRandomnessByRequestID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_arguments\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_gasAvailable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_mostRecentRequestID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_myBeaconRequests\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"slotNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelay\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_randomWords\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"\",\"type\":\"uint24\"}],\"name\":\"s_requestsIDs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_subId\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"}],\"name\":\"setCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"shouldFail\",\"type\":\"bool\"}],\"name\":\"setFail\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"reqId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"height\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"delay\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"}],\"name\":\"storeBeaconRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"}],\"name\":\"testRedeemRandomness\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelayArg\",\"type\":\"uint24\"}],\"name\":\"testRequestRandomness\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"uint24\",\"name\":\"confDelay\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"}],\"name\":\"testRequestRandomnessFulfillment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60806040523480156200001157600080fd5b50604051620018db380380620018db8339810160408190526200003491620001aa565b8233806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620000ff565b5050600280546001600160a01b0319166001600160a01b03939093169290921790915550600b805460ff191692151592909217909155600c555062000201565b336001600160a01b03821603620001595760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600080600060608486031215620001c057600080fd5b83516001600160a01b0381168114620001d857600080fd5b60208501519093508015158114620001ef57600080fd5b80925050604084015190509250925092565b6116ca80620002116000396000f3fe608060405234801561001057600080fd5b506004361061016c5760003560e01c8063a9cc4718116100cd578063ea7502ab11610081578063f2fde38b11610066578063f2fde38b1461031f578063f6eaffc814610332578063ffe97ca41461034557600080fd5b8063ea7502ab14610303578063f08c5daa1461031657600080fd5b8063cd0593df116100b2578063cd0593df146102d4578063d0705f04146102dd578063d21ea8fd146102f057600080fd5b8063a9cc4718146102a4578063c6d61301146102c157600080fd5b80637716cdaa116101245780638da5cb5b116101095780638da5cb5b1461022a5780638ea98117146102525780639d7694021461026557600080fd5b80637716cdaa1461020d57806379ba50971461022257600080fd5b8063689b77ab11610155578063689b77ab146101c45780636df57cc3146101cd578063706da1ca146101e057600080fd5b8063341867a2146101715780635f15cccc14610186575b600080fd5b61018461017f366004610e87565b6103f8565b005b6101b1610194366004610ec1565b600460209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6101b160085481565b6101846101db366004610eff565b6104ed565b6009546101f49067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016101bb565b610215610628565b6040516101bb9190610fa9565b6101846106b6565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bb565b610184610260366004610fc3565b6107b8565b610184610273366004610ff9565b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b600b546102b19060ff1681565b60405190151581526020016101bb565b6101b16102cf36600461101b565b61089e565b6101b1600c5481565b6101b16102eb366004610e87565b6109a8565b6101846102fe366004611187565b6109d9565b6101b1610311366004611250565b610a3a565b6101b1600a5481565b61018461032d366004610fc3565b610b4a565b6101b16103403660046112d4565b610b5e565b6103ae6103533660046112d4565b60056020526000908152604090205463ffffffff811690640100000000810462ffffff1690670100000000000000810461ffff16906901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1684565b6040805163ffffffff909516855262ffffff909316602085015261ffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff1660608201526080016101bb565b60025460408051602081018252600080825291517facfc6cdd000000000000000000000000000000000000000000000000000000008152919273ffffffffffffffffffffffffffffffffffffffff169163acfc6cdd9161045e91879187916004016112ed565b6000604051808303816000875af115801561047d573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526104c39190810190611315565b600083815260066020908152604090912082519293506104e7929091840190610e27565b50505050565b600083815260046020908152604080832062ffffff861684529091528120859055600c5461051b9085611404565b6040805160808101825263ffffffff928316815262ffffff958616602080830191825261ffff968716838501908152306060850190815260009b8c526005909252939099209151825491519351995173ffffffffffffffffffffffffffffffffffffffff166901000000000000000000027fffffff0000000000000000000000000000000000000000ffffffffffffffffff9a90971667010000000000000002999099167fffffff00000000000000000000000000000000000000000000ffffffffffffff93909716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000009091169890931697909717919091171692909217179092555050565b6007805461063590611418565b80601f016020809104026020016040519081016040528092919081815260200182805461066190611418565b80156106ae5780601f10610683576101008083540402835291602001916106ae565b820191906000526020600020905b81548152906001019060200180831161069157829003601f168201915b505050505081565b60015473ffffffffffffffffffffffffffffffffffffffff16331461073c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60005473ffffffffffffffffffffffffffffffffffffffff1633148015906107f8575060025473ffffffffffffffffffffffffffffffffffffffff163314155b1561082f576040517fd4e06fd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fc258faa9a17ddfdf4130b4acff63a289202e7d5f9e42f366add65368575486bc90600090a250565b600080600c546108ac610b7f565b6108b6919061146b565b9050600081600c546108c6610b7f565b6108d0919061147f565b6108da9190611498565b60025460408051602081018252600080825291517f4ffac83a000000000000000000000000000000000000000000000000000000008152939450909273ffffffffffffffffffffffffffffffffffffffff90921691634ffac83a91610948918a918c918b91906004016114ab565b6020604051808303816000875af1158015610967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098b91906114e3565b90506109998183878a6104ed565b60088190559695505050505050565b600660205281600052604060002081815481106109c457600080fd5b90600052602060002001600091509150505481565b60025473ffffffffffffffffffffffffffffffffffffffff163314610a2a576040517f66bf9c7200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a35838383610c16565b505050565b600080600c54610a48610b7f565b610a52919061146b565b9050600081600c54610a62610b7f565b610a6c919061147f565b610a769190611498565b60025460408051602081018252600080825291517fdb972c8b000000000000000000000000000000000000000000000000000000008152939450909273ffffffffffffffffffffffffffffffffffffffff9092169163db972c8b91610ae8918d918d918d918d918d91906004016114fc565b6020604051808303816000875af1158015610b07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2b91906114e3565b9050610b398183898b6104ed565b600881905598975050505050505050565b610b52610caf565b610b5b81610d32565b50565b60038181548110610b6e57600080fd5b600091825260209091200154905081565b60004661a4b1811480610b94575062066eed81145b15610c0f57606473ffffffffffffffffffffffffffffffffffffffff1663a3b1b31d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610be5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0991906114e3565b91505090565b4391505090565b600b5460ff1615610c83576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f206661696c656420696e2066756c66696c6c52616e646f6d576f7264730000006044820152606401610733565b60008381526006602090815260409091208351610ca292850190610e27565b5060076104e782826115a3565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610733565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610db1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610733565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b828054828255906000526020600020908101928215610e62579160200282015b82811115610e62578251825591602001919060010190610e47565b50610e6e929150610e72565b5090565b5b80821115610e6e5760008155600101610e73565b60008060408385031215610e9a57600080fd5b50508035926020909101359150565b803562ffffff81168114610ebc57600080fd5b919050565b60008060408385031215610ed457600080fd5b82359150610ee460208401610ea9565b90509250929050565b803561ffff81168114610ebc57600080fd5b60008060008060808587031215610f1557600080fd5b8435935060208501359250610f2c60408601610ea9565b9150610f3a60608601610eed565b905092959194509250565b6000815180845260005b81811015610f6b57602081850181015186830182015201610f4f565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610fbc6020830184610f45565b9392505050565b600060208284031215610fd557600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610fbc57600080fd5b60006020828403121561100b57600080fd5b81358015158114610fbc57600080fd5b60008060006060848603121561103057600080fd5b61103984610eed565b92506020840135915061104e60408501610ea9565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156110cd576110cd611057565b604052919050565b600067ffffffffffffffff8211156110ef576110ef611057565b5060051b60200190565b600082601f83011261110a57600080fd5b813567ffffffffffffffff81111561112457611124611057565b61115560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611086565b81815284602083860101111561116a57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121561119c57600080fd5b8335925060208085013567ffffffffffffffff808211156111bc57600080fd5b818701915087601f8301126111d057600080fd5b81356111e36111de826110d5565b611086565b81815260059190911b8301840190848101908a83111561120257600080fd5b938501935b8285101561122057843582529385019390850190611207565b96505050604087013592508083111561123857600080fd5b5050611246868287016110f9565b9150509250925092565b600080600080600060a0868803121561126857600080fd5b8535945061127860208701610eed565b935061128660408701610ea9565b9250606086013563ffffffff8116811461129f57600080fd5b9150608086013567ffffffffffffffff8111156112bb57600080fd5b6112c7888289016110f9565b9150509295509295909350565b6000602082840312156112e657600080fd5b5035919050565b83815282602082015260606040820152600061130c6060830184610f45565b95945050505050565b6000602080838503121561132857600080fd5b825167ffffffffffffffff81111561133f57600080fd5b8301601f8101851361135057600080fd5b805161135e6111de826110d5565b81815260059190911b8201830190838101908783111561137d57600080fd5b928401925b8284101561139b57835182529284019290840190611382565b979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082611413576114136113a6565b500490565b600181811c9082168061142c57607f821691505b602082108103611465577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60008261147a5761147a6113a6565b500690565b80820180821115611492576114926113d5565b92915050565b81810381811115611492576114926113d5565b84815261ffff8416602082015262ffffff831660408201526080606082015260006114d96080830184610f45565b9695505050505050565b6000602082840312156114f557600080fd5b5051919050565b86815261ffff8616602082015262ffffff8516604082015263ffffffff8416606082015260c06080820152600061153660c0830185610f45565b82810360a08401526115488185610f45565b9998505050505050505050565b601f821115610a3557600081815260208120601f850160051c8101602086101561157c5750805b601f850160051c820191505b8181101561159b57828155600101611588565b505050505050565b815167ffffffffffffffff8111156115bd576115bd611057565b6115d1816115cb8454611418565b84611555565b602080601f83116001811461162457600084156115ee5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855561159b565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561167157888601518255948401946001909101908401611652565b50858210156116ad57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000813000a", +} + +var BeaconVRFConsumerABI = BeaconVRFConsumerMetaData.ABI + +var BeaconVRFConsumerBin = BeaconVRFConsumerMetaData.Bin + +func DeployBeaconVRFConsumer(auth *bind.TransactOpts, backend bind.ContractBackend, coordinator common.Address, shouldFail bool, beaconPeriodBlocks *big.Int) (common.Address, *types.Transaction, *BeaconVRFConsumer, error) { + parsed, err := BeaconVRFConsumerMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(BeaconVRFConsumerBin), backend, coordinator, shouldFail, beaconPeriodBlocks) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &BeaconVRFConsumer{BeaconVRFConsumerCaller: BeaconVRFConsumerCaller{contract: contract}, BeaconVRFConsumerTransactor: BeaconVRFConsumerTransactor{contract: contract}, BeaconVRFConsumerFilterer: BeaconVRFConsumerFilterer{contract: contract}}, nil +} + +type BeaconVRFConsumer struct { + address common.Address + abi abi.ABI + BeaconVRFConsumerCaller + BeaconVRFConsumerTransactor + BeaconVRFConsumerFilterer +} + +type BeaconVRFConsumerCaller struct { + contract *bind.BoundContract +} + +type BeaconVRFConsumerTransactor struct { + contract *bind.BoundContract +} + +type BeaconVRFConsumerFilterer struct { + contract *bind.BoundContract +} + +type BeaconVRFConsumerSession struct { + Contract *BeaconVRFConsumer + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type BeaconVRFConsumerCallerSession struct { + Contract *BeaconVRFConsumerCaller + CallOpts bind.CallOpts +} + +type BeaconVRFConsumerTransactorSession struct { + Contract *BeaconVRFConsumerTransactor + TransactOpts bind.TransactOpts +} + +type BeaconVRFConsumerRaw struct { + Contract *BeaconVRFConsumer +} + +type BeaconVRFConsumerCallerRaw struct { + Contract *BeaconVRFConsumerCaller +} + +type BeaconVRFConsumerTransactorRaw struct { + Contract *BeaconVRFConsumerTransactor +} + +func NewBeaconVRFConsumer(address common.Address, backend bind.ContractBackend) (*BeaconVRFConsumer, error) { + abi, err := abi.JSON(strings.NewReader(BeaconVRFConsumerABI)) + if err != nil { + return nil, err + } + contract, err := bindBeaconVRFConsumer(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &BeaconVRFConsumer{address: address, abi: abi, BeaconVRFConsumerCaller: BeaconVRFConsumerCaller{contract: contract}, BeaconVRFConsumerTransactor: BeaconVRFConsumerTransactor{contract: contract}, BeaconVRFConsumerFilterer: BeaconVRFConsumerFilterer{contract: contract}}, nil +} + +func NewBeaconVRFConsumerCaller(address common.Address, caller bind.ContractCaller) (*BeaconVRFConsumerCaller, error) { + contract, err := bindBeaconVRFConsumer(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &BeaconVRFConsumerCaller{contract: contract}, nil +} + +func NewBeaconVRFConsumerTransactor(address common.Address, transactor bind.ContractTransactor) (*BeaconVRFConsumerTransactor, error) { + contract, err := bindBeaconVRFConsumer(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &BeaconVRFConsumerTransactor{contract: contract}, nil +} + +func NewBeaconVRFConsumerFilterer(address common.Address, filterer bind.ContractFilterer) (*BeaconVRFConsumerFilterer, error) { + contract, err := bindBeaconVRFConsumer(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &BeaconVRFConsumerFilterer{contract: contract}, nil +} + +func bindBeaconVRFConsumer(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := BeaconVRFConsumerMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _BeaconVRFConsumer.Contract.BeaconVRFConsumerCaller.contract.Call(opts, result, method, params...) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.BeaconVRFConsumerTransactor.contract.Transfer(opts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.BeaconVRFConsumerTransactor.contract.Transact(opts, method, params...) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _BeaconVRFConsumer.Contract.contract.Call(opts, result, method, params...) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.contract.Transfer(opts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.contract.Transact(opts, method, params...) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) Fail(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "fail") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) Fail() (bool, error) { + return _BeaconVRFConsumer.Contract.Fail(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) Fail() (bool, error) { + return _BeaconVRFConsumer.Contract.Fail(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) IBeaconPeriodBlocks(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "i_beaconPeriodBlocks") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) IBeaconPeriodBlocks() (*big.Int, error) { + return _BeaconVRFConsumer.Contract.IBeaconPeriodBlocks(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) IBeaconPeriodBlocks() (*big.Int, error) { + return _BeaconVRFConsumer.Contract.IBeaconPeriodBlocks(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) Owner() (common.Address, error) { + return _BeaconVRFConsumer.Contract.Owner(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) Owner() (common.Address, error) { + return _BeaconVRFConsumer.Contract.Owner(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) SReceivedRandomnessByRequestID(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "s_ReceivedRandomnessByRequestID", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SReceivedRandomnessByRequestID(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SReceivedRandomnessByRequestID(&_BeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) SReceivedRandomnessByRequestID(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SReceivedRandomnessByRequestID(&_BeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) SArguments(opts *bind.CallOpts) ([]byte, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "s_arguments") + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SArguments() ([]byte, error) { + return _BeaconVRFConsumer.Contract.SArguments(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) SArguments() ([]byte, error) { + return _BeaconVRFConsumer.Contract.SArguments(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) SGasAvailable(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "s_gasAvailable") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SGasAvailable() (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SGasAvailable(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) SGasAvailable() (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SGasAvailable(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) SMostRecentRequestID(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "s_mostRecentRequestID") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SMostRecentRequestID() (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SMostRecentRequestID(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) SMostRecentRequestID() (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SMostRecentRequestID(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) SMyBeaconRequests(opts *bind.CallOpts, arg0 *big.Int) (SMyBeaconRequests, + + error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "s_myBeaconRequests", arg0) + + outstruct := new(SMyBeaconRequests) + if err != nil { + return *outstruct, err + } + + outstruct.SlotNumber = *abi.ConvertType(out[0], new(uint32)).(*uint32) + outstruct.ConfirmationDelay = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + outstruct.NumWords = *abi.ConvertType(out[2], new(uint16)).(*uint16) + outstruct.Requester = *abi.ConvertType(out[3], new(common.Address)).(*common.Address) + + return *outstruct, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SMyBeaconRequests(arg0 *big.Int) (SMyBeaconRequests, + + error) { + return _BeaconVRFConsumer.Contract.SMyBeaconRequests(&_BeaconVRFConsumer.CallOpts, arg0) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) SMyBeaconRequests(arg0 *big.Int) (SMyBeaconRequests, + + error) { + return _BeaconVRFConsumer.Contract.SMyBeaconRequests(&_BeaconVRFConsumer.CallOpts, arg0) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) SRandomWords(opts *bind.CallOpts, arg0 *big.Int) (*big.Int, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "s_randomWords", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SRandomWords(arg0 *big.Int) (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SRandomWords(&_BeaconVRFConsumer.CallOpts, arg0) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) SRandomWords(arg0 *big.Int) (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SRandomWords(&_BeaconVRFConsumer.CallOpts, arg0) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) SRequestsIDs(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "s_requestsIDs", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SRequestsIDs(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SRequestsIDs(&_BeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) SRequestsIDs(arg0 *big.Int, arg1 *big.Int) (*big.Int, error) { + return _BeaconVRFConsumer.Contract.SRequestsIDs(&_BeaconVRFConsumer.CallOpts, arg0, arg1) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCaller) SSubId(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _BeaconVRFConsumer.contract.Call(opts, &out, "s_subId") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SSubId() (uint64, error) { + return _BeaconVRFConsumer.Contract.SSubId(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerCallerSession) SSubId() (uint64, error) { + return _BeaconVRFConsumer.Contract.SSubId(&_BeaconVRFConsumer.CallOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BeaconVRFConsumer.contract.Transact(opts, "acceptOwnership") +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) AcceptOwnership() (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.AcceptOwnership(&_BeaconVRFConsumer.TransactOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.AcceptOwnership(&_BeaconVRFConsumer.TransactOpts) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactor) RawFulfillRandomWords(opts *bind.TransactOpts, requestID *big.Int, randomWords []*big.Int, arguments []byte) (*types.Transaction, error) { + return _BeaconVRFConsumer.contract.Transact(opts, "rawFulfillRandomWords", requestID, randomWords, arguments) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) RawFulfillRandomWords(requestID *big.Int, randomWords []*big.Int, arguments []byte) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.RawFulfillRandomWords(&_BeaconVRFConsumer.TransactOpts, requestID, randomWords, arguments) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorSession) RawFulfillRandomWords(requestID *big.Int, randomWords []*big.Int, arguments []byte) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.RawFulfillRandomWords(&_BeaconVRFConsumer.TransactOpts, requestID, randomWords, arguments) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactor) SetCoordinator(opts *bind.TransactOpts, coordinator common.Address) (*types.Transaction, error) { + return _BeaconVRFConsumer.contract.Transact(opts, "setCoordinator", coordinator) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SetCoordinator(coordinator common.Address) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.SetCoordinator(&_BeaconVRFConsumer.TransactOpts, coordinator) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorSession) SetCoordinator(coordinator common.Address) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.SetCoordinator(&_BeaconVRFConsumer.TransactOpts, coordinator) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactor) SetFail(opts *bind.TransactOpts, shouldFail bool) (*types.Transaction, error) { + return _BeaconVRFConsumer.contract.Transact(opts, "setFail", shouldFail) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) SetFail(shouldFail bool) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.SetFail(&_BeaconVRFConsumer.TransactOpts, shouldFail) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorSession) SetFail(shouldFail bool) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.SetFail(&_BeaconVRFConsumer.TransactOpts, shouldFail) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactor) StoreBeaconRequest(opts *bind.TransactOpts, reqId *big.Int, height *big.Int, delay *big.Int, numWords uint16) (*types.Transaction, error) { + return _BeaconVRFConsumer.contract.Transact(opts, "storeBeaconRequest", reqId, height, delay, numWords) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) StoreBeaconRequest(reqId *big.Int, height *big.Int, delay *big.Int, numWords uint16) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.StoreBeaconRequest(&_BeaconVRFConsumer.TransactOpts, reqId, height, delay, numWords) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorSession) StoreBeaconRequest(reqId *big.Int, height *big.Int, delay *big.Int, numWords uint16) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.StoreBeaconRequest(&_BeaconVRFConsumer.TransactOpts, reqId, height, delay, numWords) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactor) TestRedeemRandomness(opts *bind.TransactOpts, subID *big.Int, requestID *big.Int) (*types.Transaction, error) { + return _BeaconVRFConsumer.contract.Transact(opts, "testRedeemRandomness", subID, requestID) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) TestRedeemRandomness(subID *big.Int, requestID *big.Int) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.TestRedeemRandomness(&_BeaconVRFConsumer.TransactOpts, subID, requestID) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorSession) TestRedeemRandomness(subID *big.Int, requestID *big.Int) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.TestRedeemRandomness(&_BeaconVRFConsumer.TransactOpts, subID, requestID) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactor) TestRequestRandomness(opts *bind.TransactOpts, numWords uint16, subID *big.Int, confirmationDelayArg *big.Int) (*types.Transaction, error) { + return _BeaconVRFConsumer.contract.Transact(opts, "testRequestRandomness", numWords, subID, confirmationDelayArg) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) TestRequestRandomness(numWords uint16, subID *big.Int, confirmationDelayArg *big.Int) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.TestRequestRandomness(&_BeaconVRFConsumer.TransactOpts, numWords, subID, confirmationDelayArg) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorSession) TestRequestRandomness(numWords uint16, subID *big.Int, confirmationDelayArg *big.Int) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.TestRequestRandomness(&_BeaconVRFConsumer.TransactOpts, numWords, subID, confirmationDelayArg) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactor) TestRequestRandomnessFulfillment(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte) (*types.Transaction, error) { + return _BeaconVRFConsumer.contract.Transact(opts, "testRequestRandomnessFulfillment", subID, numWords, confDelay, callbackGasLimit, arguments) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) TestRequestRandomnessFulfillment(subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.TestRequestRandomnessFulfillment(&_BeaconVRFConsumer.TransactOpts, subID, numWords, confDelay, callbackGasLimit, arguments) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorSession) TestRequestRandomnessFulfillment(subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.TestRequestRandomnessFulfillment(&_BeaconVRFConsumer.TransactOpts, subID, numWords, confDelay, callbackGasLimit, arguments) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _BeaconVRFConsumer.contract.Transact(opts, "transferOwnership", to) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.TransferOwnership(&_BeaconVRFConsumer.TransactOpts, to) +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _BeaconVRFConsumer.Contract.TransferOwnership(&_BeaconVRFConsumer.TransactOpts, to) +} + +type BeaconVRFConsumerCoordinatorUpdatedIterator struct { + Event *BeaconVRFConsumerCoordinatorUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BeaconVRFConsumerCoordinatorUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BeaconVRFConsumerCoordinatorUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(BeaconVRFConsumerCoordinatorUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *BeaconVRFConsumerCoordinatorUpdatedIterator) Error() error { + return it.fail +} + +func (it *BeaconVRFConsumerCoordinatorUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BeaconVRFConsumerCoordinatorUpdated struct { + Coordinator common.Address + Raw types.Log +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerFilterer) FilterCoordinatorUpdated(opts *bind.FilterOpts, coordinator []common.Address) (*BeaconVRFConsumerCoordinatorUpdatedIterator, error) { + + var coordinatorRule []interface{} + for _, coordinatorItem := range coordinator { + coordinatorRule = append(coordinatorRule, coordinatorItem) + } + + logs, sub, err := _BeaconVRFConsumer.contract.FilterLogs(opts, "CoordinatorUpdated", coordinatorRule) + if err != nil { + return nil, err + } + return &BeaconVRFConsumerCoordinatorUpdatedIterator{contract: _BeaconVRFConsumer.contract, event: "CoordinatorUpdated", logs: logs, sub: sub}, nil +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerFilterer) WatchCoordinatorUpdated(opts *bind.WatchOpts, sink chan<- *BeaconVRFConsumerCoordinatorUpdated, coordinator []common.Address) (event.Subscription, error) { + + var coordinatorRule []interface{} + for _, coordinatorItem := range coordinator { + coordinatorRule = append(coordinatorRule, coordinatorItem) + } + + logs, sub, err := _BeaconVRFConsumer.contract.WatchLogs(opts, "CoordinatorUpdated", coordinatorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(BeaconVRFConsumerCoordinatorUpdated) + if err := _BeaconVRFConsumer.contract.UnpackLog(event, "CoordinatorUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerFilterer) ParseCoordinatorUpdated(log types.Log) (*BeaconVRFConsumerCoordinatorUpdated, error) { + event := new(BeaconVRFConsumerCoordinatorUpdated) + if err := _BeaconVRFConsumer.contract.UnpackLog(event, "CoordinatorUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BeaconVRFConsumerOwnershipTransferRequestedIterator struct { + Event *BeaconVRFConsumerOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BeaconVRFConsumerOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BeaconVRFConsumerOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(BeaconVRFConsumerOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *BeaconVRFConsumerOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *BeaconVRFConsumerOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BeaconVRFConsumerOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BeaconVRFConsumerOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _BeaconVRFConsumer.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &BeaconVRFConsumerOwnershipTransferRequestedIterator{contract: _BeaconVRFConsumer.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *BeaconVRFConsumerOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _BeaconVRFConsumer.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(BeaconVRFConsumerOwnershipTransferRequested) + if err := _BeaconVRFConsumer.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerFilterer) ParseOwnershipTransferRequested(log types.Log) (*BeaconVRFConsumerOwnershipTransferRequested, error) { + event := new(BeaconVRFConsumerOwnershipTransferRequested) + if err := _BeaconVRFConsumer.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BeaconVRFConsumerOwnershipTransferredIterator struct { + Event *BeaconVRFConsumerOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BeaconVRFConsumerOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BeaconVRFConsumerOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(BeaconVRFConsumerOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *BeaconVRFConsumerOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *BeaconVRFConsumerOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BeaconVRFConsumerOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BeaconVRFConsumerOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _BeaconVRFConsumer.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &BeaconVRFConsumerOwnershipTransferredIterator{contract: _BeaconVRFConsumer.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *BeaconVRFConsumerOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _BeaconVRFConsumer.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(BeaconVRFConsumerOwnershipTransferred) + if err := _BeaconVRFConsumer.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_BeaconVRFConsumer *BeaconVRFConsumerFilterer) ParseOwnershipTransferred(log types.Log) (*BeaconVRFConsumerOwnershipTransferred, error) { + event := new(BeaconVRFConsumerOwnershipTransferred) + if err := _BeaconVRFConsumer.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type SMyBeaconRequests struct { + SlotNumber uint32 + ConfirmationDelay *big.Int + NumWords uint16 + Requester common.Address +} + +func (_BeaconVRFConsumer *BeaconVRFConsumer) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _BeaconVRFConsumer.abi.Events["CoordinatorUpdated"].ID: + return _BeaconVRFConsumer.ParseCoordinatorUpdated(log) + case _BeaconVRFConsumer.abi.Events["OwnershipTransferRequested"].ID: + return _BeaconVRFConsumer.ParseOwnershipTransferRequested(log) + case _BeaconVRFConsumer.abi.Events["OwnershipTransferred"].ID: + return _BeaconVRFConsumer.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (BeaconVRFConsumerCoordinatorUpdated) Topic() common.Hash { + return common.HexToHash("0xc258faa9a17ddfdf4130b4acff63a289202e7d5f9e42f366add65368575486bc") +} + +func (BeaconVRFConsumerOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (BeaconVRFConsumerOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_BeaconVRFConsumer *BeaconVRFConsumer) Address() common.Address { + return _BeaconVRFConsumer.address +} + +type BeaconVRFConsumerInterface interface { + Fail(opts *bind.CallOpts) (bool, error) + + IBeaconPeriodBlocks(opts *bind.CallOpts) (*big.Int, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + SReceivedRandomnessByRequestID(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) + + SArguments(opts *bind.CallOpts) ([]byte, error) + + SGasAvailable(opts *bind.CallOpts) (*big.Int, error) + + SMostRecentRequestID(opts *bind.CallOpts) (*big.Int, error) + + SMyBeaconRequests(opts *bind.CallOpts, arg0 *big.Int) (SMyBeaconRequests, + + error) + + SRandomWords(opts *bind.CallOpts, arg0 *big.Int) (*big.Int, error) + + SRequestsIDs(opts *bind.CallOpts, arg0 *big.Int, arg1 *big.Int) (*big.Int, error) + + SSubId(opts *bind.CallOpts) (uint64, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + RawFulfillRandomWords(opts *bind.TransactOpts, requestID *big.Int, randomWords []*big.Int, arguments []byte) (*types.Transaction, error) + + SetCoordinator(opts *bind.TransactOpts, coordinator common.Address) (*types.Transaction, error) + + SetFail(opts *bind.TransactOpts, shouldFail bool) (*types.Transaction, error) + + StoreBeaconRequest(opts *bind.TransactOpts, reqId *big.Int, height *big.Int, delay *big.Int, numWords uint16) (*types.Transaction, error) + + TestRedeemRandomness(opts *bind.TransactOpts, subID *big.Int, requestID *big.Int) (*types.Transaction, error) + + TestRequestRandomness(opts *bind.TransactOpts, numWords uint16, subID *big.Int, confirmationDelayArg *big.Int) (*types.Transaction, error) + + TestRequestRandomnessFulfillment(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterCoordinatorUpdated(opts *bind.FilterOpts, coordinator []common.Address) (*BeaconVRFConsumerCoordinatorUpdatedIterator, error) + + WatchCoordinatorUpdated(opts *bind.WatchOpts, sink chan<- *BeaconVRFConsumerCoordinatorUpdated, coordinator []common.Address) (event.Subscription, error) + + ParseCoordinatorUpdated(log types.Log) (*BeaconVRFConsumerCoordinatorUpdated, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BeaconVRFConsumerOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *BeaconVRFConsumerOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*BeaconVRFConsumerOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BeaconVRFConsumerOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *BeaconVRFConsumerOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*BeaconVRFConsumerOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ocr2vrf/generated/vrf_coordinator/vrf_coordinator.go b/core/gethwrappers/ocr2vrf/generated/vrf_coordinator/vrf_coordinator.go new file mode 100644 index 00000000000..f20d5494452 --- /dev/null +++ b/core/gethwrappers/ocr2vrf/generated/vrf_coordinator/vrf_coordinator.go @@ -0,0 +1,3870 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package vrf_coordinator + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +type ECCArithmeticG1Point struct { + P [2]*big.Int +} + +type VRFBeaconTypesCallback struct { + RequestID *big.Int + NumWords uint16 + Requester common.Address + Arguments []byte + GasAllowance *big.Int + SubID *big.Int + GasPrice *big.Int + WeiPerUnitLink *big.Int +} + +type VRFBeaconTypesCoordinatorConfig struct { + UseReasonableGasPrice bool + ReentrancyLock bool + Paused bool + PremiumPercentage uint8 + UnusedGasPenaltyPercent uint8 + StalenessSeconds uint32 + RedeemableRequestGasOverhead uint32 + CallbackRequestGasOverhead uint32 + ReasonableGasPriceStalenessBlocks uint32 + FallbackWeiPerUnitLink *big.Int +} + +type VRFBeaconTypesCostedCallback struct { + Callback VRFBeaconTypesCallback + Price *big.Int +} + +type VRFBeaconTypesOutputServed struct { + Height uint64 + ConfirmationDelay *big.Int + ProofG1X *big.Int + ProofG1Y *big.Int +} + +type VRFBeaconTypesVRFOutput struct { + BlockHeight uint64 + ConfirmationDelay *big.Int + VrfOutput ECCArithmeticG1Point + Callbacks []VRFBeaconTypesCostedCallback + ShouldStore bool +} + +type VRFCoordinatorCallbackConfig struct { + MaxCallbackGasLimit uint32 + MaxCallbackArgumentsLength uint32 +} + +var VRFCoordinatorMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"beaconPeriodBlocksArg\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"BeaconPeriodMustBePositive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestHeight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"earliestAllowed\",\"type\":\"uint256\"}],\"name\":\"BlockTooRecent\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16[10]\",\"name\":\"confirmationDelays\",\"type\":\"uint16[10]\"},{\"internalType\":\"uint8\",\"name\":\"violatingIndex\",\"type\":\"uint8\"}],\"name\":\"ConfirmationDelaysNotIncreasing\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractPaused\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorNotRegistered\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasAllowance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLeft\",\"type\":\"uint256\"}],\"name\":\"GasAllowanceExceedsGasLeft\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportHeight\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"separatorHeight\",\"type\":\"uint64\"}],\"name\":\"HistoryDomainSeparatorTooOld\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"actualBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requiredBalance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"expectedLength\",\"type\":\"uint16\"},{\"internalType\":\"uint256\",\"name\":\"actualLength\",\"type\":\"uint256\"}],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"InvalidConsumer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCoordinatorConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidJuelsConversion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numRecipients\",\"type\":\"uint256\"}],\"name\":\"InvalidNumberOfRecipients\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestedSubID\",\"type\":\"uint256\"}],\"name\":\"InvalidSubscription\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"requestedVersion\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"coordinatorVersion\",\"type\":\"uint8\"}],\"name\":\"MigrationVersionMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProducer\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedOwner\",\"type\":\"address\"}],\"name\":\"MustBeRequestedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"MustBeSubOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NativePaymentGiven\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoWordsRequested\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16[10]\",\"name\":\"confDelays\",\"type\":\"uint16[10]\"}],\"name\":\"NonZeroDelayAfterZeroDelay\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnMigrationNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableFromLink\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PendingRequestExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"producer\",\"type\":\"address\"}],\"name\":\"ProducerAlreadyInitialized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requestHeight\",\"type\":\"uint256\"}],\"name\":\"RandomnessNotAvailable\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestHeight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"confDelay\",\"type\":\"uint256\"}],\"name\":\"RandomnessSeedNotFoundForCallbacks\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numRecipients\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numPayments\",\"type\":\"uint256\"}],\"name\":\"RecipientsPaymentsMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Reentrant\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"expected\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"actual\",\"type\":\"address\"}],\"name\":\"ResponseMustBeRetrievedByRequester\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyConsumers\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyRequestsReplaceContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySlotsReplaceContract\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"TooManyWords\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockHeight\",\"type\":\"uint256\"}],\"name\":\"UniverseHasEndedBangBangBang\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxCallbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCallbackArgumentsLength\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structVRFCoordinator.CallbackConfig\",\"name\":\"newConfig\",\"type\":\"tuple\"}],\"name\":\"CallbackConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"useReasonableGasPrice\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyLock\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"premiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"unusedGasPenaltyPercent\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"redeemableRequestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"callbackRequestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"reasonableGasPriceStalenessBlocks\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structVRFBeaconTypes.CoordinatorConfig\",\"name\":\"coordinatorConfig\",\"type\":\"tuple\"}],\"name\":\"CoordinatorConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorDeregistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"newVersion\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newCoordinator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"}],\"name\":\"MigrationCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"recentBlockHeight\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint192\",\"name\":\"juelsPerFeeCoin\",\"type\":\"uint192\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"reasonableGasPrice\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"height\",\"type\":\"uint64\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelay\",\"type\":\"uint24\"},{\"internalType\":\"uint256\",\"name\":\"proofG1X\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"proofG1Y\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structVRFBeaconTypes.OutputServed[]\",\"name\":\"outputsServed\",\"type\":\"tuple[]\"}],\"name\":\"OutputsServed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"name\":\"PauseFlagChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"requestIDs\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"successfulFulfillment\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"truncatedErrorData\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"uint96[]\",\"name\":\"subBalances\",\"type\":\"uint96[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"subIDs\",\"type\":\"uint256[]\"}],\"name\":\"RandomWordsFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nextBeaconOutputHeight\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint24\",\"name\":\"confDelay\",\"type\":\"uint24\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasAllowance\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasPrice\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"weiPerUnitLink\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"costJuels\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSubBalance\",\"type\":\"uint256\"}],\"name\":\"RandomnessFulfillmentRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"}],\"name\":\"RandomnessRedeemed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nextBeaconOutputHeight\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint24\",\"name\":\"confDelay\",\"type\":\"uint24\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"costJuels\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSubBalance\",\"type\":\"uint256\"}],\"name\":\"RandomnessRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SubscriptionCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"SubscriptionConsumerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"SubscriptionConsumerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"SubscriptionCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"SubscriptionFunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"SubscriptionOwnerTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"SubscriptionOwnerTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_CONSUMERS\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_NUM_WORDS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NUM_CONF_DELAYS\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"acceptSubscriptionOwnerTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"addConsumer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"recipients\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"paymentsInJuels\",\"type\":\"uint256[]\"}],\"name\":\"batchTransferLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"cancelSubscription\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"createSubscription\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"deregisterMigratableCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"name\":\"getCallbackMemo\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfirmationDelays\",\"outputs\":[{\"internalType\":\"uint24[8]\",\"name\":\"\",\"type\":\"uint24[8]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"getFulfillmentFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"getSubscription\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint64\",\"name\":\"pendingFulfillments\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"consumers\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSubscriptionLinkBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_beaconPeriodBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_link\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIVRFMigration\",\"name\":\"newCoordinator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"encodedRequest\",\"type\":\"bytes\"}],\"name\":\"migrate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"migrationVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onMigration\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"blockHeight\",\"type\":\"uint64\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelay\",\"type\":\"uint24\"},{\"components\":[{\"internalType\":\"uint256[2]\",\"name\":\"p\",\"type\":\"uint256[2]\"}],\"internalType\":\"structECCArithmetic.G1Point\",\"name\":\"vrfOutput\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"},{\"internalType\":\"uint96\",\"name\":\"gasAllowance\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weiPerUnitLink\",\"type\":\"uint256\"}],\"internalType\":\"structVRFBeaconTypes.Callback\",\"name\":\"callback\",\"type\":\"tuple\"},{\"internalType\":\"uint96\",\"name\":\"price\",\"type\":\"uint96\"}],\"internalType\":\"structVRFBeaconTypes.CostedCallback[]\",\"name\":\"callbacks\",\"type\":\"tuple[]\"},{\"internalType\":\"bool\",\"name\":\"shouldStore\",\"type\":\"bool\"}],\"internalType\":\"structVRFBeaconTypes.VRFOutput[]\",\"name\":\"vrfOutputs\",\"type\":\"tuple[]\"},{\"internalType\":\"uint192\",\"name\":\"juelsPerFeeCoin\",\"type\":\"uint192\"},{\"internalType\":\"uint64\",\"name\":\"reasonableGasPrice\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"blockHeight\",\"type\":\"uint64\"}],\"name\":\"processVRFOutputs\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"containsNewOutputs\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requestID\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"redeemRandomness\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"randomness\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"registerMigratableCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"removeConsumer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"uint24\",\"name\":\"confDelay\",\"type\":\"uint24\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"requestRandomness\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"uint24\",\"name\":\"confDelay\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"arguments\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"requestRandomnessFulfillment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"requestSubscriptionOwnerTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_callbackConfig\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"maxCallbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCallbackArgumentsLength\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_coordinatorConfig\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"useReasonableGasPrice\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyLock\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"premiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"unusedGasPenaltyPercent\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"redeemableRequestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"callbackRequestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"reasonableGasPriceStalenessBlocks\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_pendingRequests\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"slotNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"confirmationDelay\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"numWords\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_producer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxCallbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCallbackArgumentsLength\",\"type\":\"uint32\"}],\"internalType\":\"structVRFCoordinator.CallbackConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"setCallbackConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint24[8]\",\"name\":\"confDelays\",\"type\":\"uint24[8]\"}],\"name\":\"setConfirmationDelays\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"useReasonableGasPrice\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyLock\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"premiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"unusedGasPenaltyPercent\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"redeemableRequestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"callbackRequestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"reasonableGasPriceStalenessBlocks\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"uint96\"}],\"internalType\":\"structVRFBeaconTypes.CoordinatorConfig\",\"name\":\"coordinatorConfig\",\"type\":\"tuple\"}],\"name\":\"setCoordinatorConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"pause\",\"type\":\"bool\"}],\"name\":\"setPauseFlag\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"producer\",\"type\":\"address\"}],\"name\":\"setProducer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"juelsAmount\",\"type\":\"uint256\"}],\"name\":\"transferLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60c06040523480156200001157600080fd5b50604051620062f5380380620062f5833981016040819052620000349162000239565b8033806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf816200018e565b5050506001600160a01b03166080908152604080519182018152600080835260208301819052908201819052662386f26fc10000606090920191909152642386f26fc160b01b6006556004805463ffffffff60281b191668ffffffff00000000001790558290036200014457604051632abc297960e01b815260040160405180910390fd5b60a0829052600e805465ffffffffffff16906000620001638362000278565b91906101000a81548165ffffffffffff021916908365ffffffffffff160217905550505050620002ac565b336001600160a01b03821603620001e85760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600080604083850312156200024d57600080fd5b825160208401519092506001600160a01b03811681146200026d57600080fd5b809150509250929050565b600065ffffffffffff808316818103620002a257634e487b7160e01b600052601160045260246000fd5b6001019392505050565b60805160a051615fdd620003186000396000818161075f01528181611ca301528181613cb301528181613ce201528181613d1a015261430e01526000818161047501528181610bb501528181611a410152818161237b01528181612d610152612df60152615fdd6000f3fe6080604052600436106101d65760003560e01c806304104edb146101db5780630ae09540146101fd57806316f6ee9a1461021d578063294daa491461025d5780632b38bafc1461027f5780632f7527cc1461029f5780633e79167f146102b457806340d6bb82146102d457806347c3e2cb146102ea5780634ffac83a14610385578063597d2f3c146103985780635d06b4ab146103b657806364d51a2a146103d657806373433a2f146103fe57806376f2e3f41461041e57806379ba50971461044e5780637d253aff1461046357806385c64e11146104a45780638c7cba66146104c65780638da5cb5b146104e65780638da92e71146105045780638eef585f146105245780639e20103614610544578063a21a23e414610564578063a4c0ed3614610579578063acfc6cdd14610599578063b2a7cac5146105c6578063b79fa6f7146105e6578063bd58017f146106cd578063bec4c08c146106ed578063c3fbb6fd1461070d578063cb6317971461072d578063cd0593df1461074d578063ce3f471914610781578063dac83d29146107a1578063db972c8b146107c1578063dc311dd3146107d4578063e30afa4a14610804578063f2fde38b14610849578063f99b1d6814610869578063f9c45ced14610889575b600080fd5b3480156101e757600080fd5b506101fb6101f6366004614abd565b6108a9565b005b34801561020957600080fd5b506101fb610218366004614ae1565b610a5e565b34801561022957600080fd5b5061024a610238366004614b11565b6000908152600c602052604090205490565b6040519081526020015b60405180910390f35b34801561026957600080fd5b5060015b60405160ff9091168152602001610254565b34801561028b57600080fd5b506101fb61029a366004614abd565b610cc0565b3480156102ab57600080fd5b5061026d600881565b3480156102c057600080fd5b506101fb6102cf366004614b2a565b610d21565b3480156102e057600080fd5b5061024a6103e881565b3480156102f657600080fd5b50610348610305366004614b11565b60106020526000908152604090205463ffffffff811690600160201b810462ffffff1690600160381b810461ffff1690600160481b90046001600160a01b031684565b6040805163ffffffff909516855262ffffff909316602085015261ffff909116918301919091526001600160a01b03166060820152608001610254565b61024a610393366004614cac565b610dd2565b3480156103a457600080fd5b506002546001600160601b031661024a565b3480156103c257600080fd5b506101fb6103d1366004614abd565b610f7e565b3480156103e257600080fd5b506103eb606481565b60405161ffff9091168152602001610254565b34801561040a57600080fd5b506101fb610419366004614d57565b61102a565b34801561042a57600080fd5b5061043e610439366004614dd9565b611115565b6040519015158152602001610254565b34801561045a57600080fd5b506101fb611453565b34801561046f57600080fd5b506104977f000000000000000000000000000000000000000000000000000000000000000081565b6040516102549190614e5b565b3480156104b057600080fd5b506104b96114fd565b6040516102549190614e6f565b3480156104d257600080fd5b506101fb6104e1366004614ec3565b611562565b3480156104f257600080fd5b506000546001600160a01b0316610497565b34801561051057600080fd5b506101fb61051f366004614f1d565b6115d6565b34801561053057600080fd5b506101fb61053f366004614f3a565b611640565b34801561055057600080fd5b5061024a61055f366004614f65565b61167c565b34801561057057600080fd5b5061024a61179d565b34801561058557600080fd5b506101fb610594366004615019565b6119e3565b3480156105a557600080fd5b506105b96105b4366004615068565b611bce565b60405161025491906150f2565b3480156105d257600080fd5b506101fb6105e1366004614b11565b611dd2565b3480156105f257600080fd5b506004546005546106629160ff80821692610100830482169262010000810483169263010000008204811692600160201b83049091169163ffffffff600160281b8204811692600160481b8304821692600160681b8104831692600160881b90910416906001600160601b03168a565b604080519a15158b5298151560208b01529615159789019790975260ff948516606089015292909316608087015263ffffffff90811660a087015291821660c0860152811660e08501529091166101008301526001600160601b031661012082015261014001610254565b3480156106d957600080fd5b50600a54610497906001600160a01b031681565b3480156106f957600080fd5b506101fb610708366004614ae1565b611f03565b34801561071957600080fd5b506101fb610728366004615105565b6120bf565b34801561073957600080fd5b506101fb610748366004614ae1565b6125ac565b34801561075957600080fd5b5061024a7f000000000000000000000000000000000000000000000000000000000000000081565b34801561078d57600080fd5b506101fb61079c366004615159565b612899565b3480156107ad57600080fd5b506101fb6107bc366004614ae1565b6128b2565b61024a6107cf36600461519a565b6129c3565b3480156107e057600080fd5b506107f46107ef366004614b11565b612c21565b6040516102549493929190615272565b34801561081057600080fd5b50600b5461082c9063ffffffff80821691600160201b90041682565b6040805163ffffffff938416815292909116602083015201610254565b34801561085557600080fd5b506101fb610864366004614abd565b612d0e565b34801561087557600080fd5b506101fb6108843660046152be565b612d1f565b34801561089557600080fd5b5061024a6108a43660046152ea565b612e88565b6108b1612f9f565b60095460005b81811015610a3657826001600160a01b0316600982815481106108dc576108dc615330565b6000918252602090912001546001600160a01b031603610a2457600961090360018461535c565b8154811061091357610913615330565b600091825260209091200154600980546001600160a01b03909216918390811061093f5761093f615330565b600091825260209091200180546001600160a01b0319166001600160a01b039290921691909117905582600961097660018561535c565b8154811061098657610986615330565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060098054806109c5576109c561536f565b600082815260209020810160001990810180546001600160a01b03191690550190556040517ff80a1a97fd42251f3c33cda98635e7399253033a6774fe37cd3f650b5282af3790610a17908590614e5b565b60405180910390a1505050565b80610a2e81615385565b9150506108b7565b5081604051635428d44960e01b8152600401610a529190614e5b565b60405180910390fd5b50565b60008281526007602052604090205482906001600160a01b031680610a995760405163c5171ee960e01b815260048101839052602401610a52565b336001600160a01b03821614610ac45780604051636c51fda960e11b8152600401610a529190614e5b565b600454610100900460ff1615610aed5760405163769dd35360e11b815260040160405180910390fd5b600084815260086020526040902054600160601b90046001600160401b031615610b2a57604051631685ecdd60e31b815260040160405180910390fd5b6000848152600860209081526040918290208251808401909352546001600160601b038116808452600160601b9091046001600160401b031691830191909152610b7386612ff4565b600280546001600160601b03169082906000610b8f838561539e565b92506101000a8154816001600160601b0302191690836001600160601b031602179055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb87846001600160601b03166040518363ffffffff1660e01b8152600401610c0a9291906153c5565b6020604051808303816000875af1158015610c29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4d91906153de565b610c7d5760405163cf47918160e01b81526001600160601b03808316600483015283166024820152604401610a52565b867f3784f77e8e883de95b5d47cd713ced01229fa74d118c0a462224bcb0516d43f18784604051610caf9291906153fb565b60405180910390a250505050505050565b610cc8612f9f565b600a546001600160a01b031615610cff57600a5460405163ea6d390560e01b8152610a52916001600160a01b031690600401614e5b565b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b610d29612f9f565b6064610d3b60a0830160808401615437565b60ff161180610d555750610d556040820160208301614f1d565b80610d6b5750610d6b6060820160408301614f1d565b15610d895760405163b0e7bd8360e01b815260040160405180910390fd5b806004610d96828261549d565b9050507e28d3a46e95e67def989d41c66eb331add9809460b95b5fb4eb006157728fc581604051610dc79190615670565b60405180910390a150565b60045460009062010000900460ff1615610dff5760405163ab35696f60e01b815260040160405180910390fd5b600454610100900460ff1615610e285760405163769dd35360e11b815260040160405180910390fd5b3415610e4957604051630b829bad60e21b8152346004820152602401610a52565b6000806000610e5a88338989613143565b925092509250600080610e6d338b61328e565b600087815260106020908152604091829020885181548a8401518b8601516060808e015163ffffffff90951666ffffffffffffff1990941693909317600160201b62ffffff9384160217600160381b600160e81b031916600160381b61ffff92831602600160481b600160e81b03191617600160481b6001600160a01b03909516949094029390931790935584513381526001600160401b038b1694810194909452918e169383019390935281018e9052908c16608082015260a081018390526001600160601b03821660c0820152919350915085907fb7933fba96b6b452eb44f99fdc08052a45dff82363d59abaff0456931c3d24599060e00160405180910390a2509298975050505050505050565b610f86612f9f565b610f8f8161346a565b15610faf578060405163ac8a27ef60e01b8152600401610a529190614e5b565b600980546001810182556000919091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0180546001600160a01b0319166001600160a01b0383161790556040517fb7cabbfc11e66731fc77de0444614282023bcbd41d16781c753a431d0af0162590610dc7908390614e5b565b600a546001600160a01b0316331461105557604051634bea32db60e11b815260040160405180910390fd5b828015806110635750601f81115b1561108457604051634ecc4fef60e01b815260048101829052602401610a52565b8082146110a85760405163339f8a9d60e01b8152610a529082908490600401615758565b60005b8181101561110d576110fb8686838181106110c8576110c8615330565b90506020020160208101906110dd9190614abd565b8585848181106110ef576110ef615330565b90506020020135612d1f565b8061110581615385565b9150506110ab565b505050505050565b600a546000906001600160a01b0316331461114357604051634bea32db60e11b815260040160405180910390fd5b60045462010000900460ff161561116d5760405163ab35696f60e01b815260040160405180910390fd5b6001600160c01b038416156111aa57600680546001600160601b038616600160a01b02600160201b600160a01b0390911663ffffffff4216171790555b6001600160401b038316156111ff5760068054436001600160401b03908116600160201b02600160201b600160601b0319918716600160601b0291909116600160201b600160a01b0319909216919091171790555b600080866001600160401b0381111561121a5761121a614b68565b60405190808252806020026020018201604052801561125357816020015b6112406148f6565b8152602001906001900390816112385790505b50905060005b8781101561135557600089898381811061127557611275615330565b90506020028101906112879190615766565b611290906158ea565b9050600061129f82888b6134d3565b905085806112aa5750805b604083015151519096501515806112c957506040820151516020015115155b15611340576040805160808101825283516001600160401b0316815260208085015162ffffff168183015284830180515151938301939093529151519091015160608201528451859061ffff881690811061132657611326615330565b6020026020010181905250848061133c906159d0565b9550505b5050808061134d90615385565b915050611259565b5060008261ffff166001600160401b0381111561137457611374614b68565b6040519080825280602002602001820160405280156113ad57816020015b61139a6148f6565b8152602001906001900390816113925790505b50905060005b8361ffff16811015611409578281815181106113d1576113d1615330565b60200260200101518282815181106113eb576113eb615330565b6020026020010181905250808061140190615385565b9150506113b3565b507ff10ea936d00579b4c52035ee33bf46929646b3aa87554c565d8fb2c7aa549c448588888460405161143f94939291906159f1565b60405180910390a150505095945050505050565b6001546001600160a01b031633146114a65760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b6044820152606401610a52565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61150561492c565b6040805161010081019182905290600f90600890826000855b82829054906101000a900462ffffff1662ffffff168152602001906003019060208260020104928301926001038202915080841161151e5790505050505050905090565b61156a612f9f565b8051600b80546020808501805163ffffffff908116600160201b026001600160401b031990941695811695861793909317909355604080519485529251909116908301527f0cc54509a45ab33cd67614d4a2892c083ecf8fb43b9d29f6ea8130b9023e51df9101610dc7565b6115de612f9f565b60045460ff6201000090910416151581151514610a5b5760048054821515620100000262ff0000199091161790556040517f49ba7c1de2d8853088b6270e43df2118516b217f38b917dd2b80dea360860fbe90610dc790831515815260200190565b600a546001600160a01b0316331461166b57604051634bea32db60e11b815260040160405180910390fd5b611678600f82600861494b565b5050565b604080516101408101825260045460ff80821615158352610100808304821615156020808601919091526201000084048316151585870152630100000084048316606080870191909152600160201b808604909416608080880191909152600160281b860463ffffffff90811660a0890152600160481b8704811660c0890152600160681b8704811660e0890152600160881b9096048616938701939093526005546001600160601b039081166101208801528751938401885260065480871685526001600160401b03958104861693850193909352600160601b830490941696830196909652600160a01b90049091169381019390935260009283926117889288169187919061366b565b50506001600160601b03169695505050505050565b600454600090610100900460ff16156117c95760405163769dd35360e11b815260040160405180910390fd5b60045462010000900460ff16156117f35760405163ab35696f60e01b815260040160405180910390fd5b60003361180160014361535c565b6001546040516001600160601b0319606094851b81166020830152924060348201523090931b90911660548301526001600160c01b0319600160a01b90910460c01b16606882015260700160408051808303601f19018152919052805160209091012060018054919250600160a01b9091046001600160401b031690601461188883615a86565b91906101000a8154816001600160401b0302191690836001600160401b03160217905550506000806001600160401b038111156118c7576118c7614b68565b6040519080825280602002602001820160405280156118f0578160200160208202803683370190505b5060408051808201825260008082526020808301828152878352600882528483209351845491516001600160601b039091166001600160a01b031992831617600160601b6001600160401b039092169190910217909355835160608101855233815280820183815281860187815289855260078452959093208151815486166001600160a01b03918216178255935160018201805490961694169390931790935592518051949550919390926119ad9260028501929101906149e9565b505060405133915083907f1d3015d7ba850fa198dc7b1a3f5d42779313a681035f77c8c03764c61005518d90600090a350905090565b600454610100900460ff1615611a0c5760405163769dd35360e11b815260040160405180910390fd5b60045462010000900460ff1615611a365760405163ab35696f60e01b815260040160405180910390fd5b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611a7f576040516344b0e3c360e01b815260040160405180910390fd5b60208114611aa557604051636865567560e01b8152610a52906020908390600401615aaa565b6000611ab382840184614b11565b6000818152600760205260409020549091506001600160a01b0316611aee5760405163c5171ee960e01b815260048101829052602401610a52565b600081815260086020526040812080546001600160601b031691869190611b158385615abe565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555084600260008282829054906101000a90046001600160601b0316611b5d9190615abe565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550817f1ced9348ff549fceab2ac57cd3a9de38edaaab274b725ee82c23e8fc8c4eec7a828784611bb09190615ade565b604051611bbe929190615758565b60405180910390a2505050505050565b600454606090610100900460ff1615611bfa5760405163769dd35360e11b815260040160405180910390fd5b60008381526010602081815260408084208151608081018352815463ffffffff8116825262ffffff600160201b8204168286015261ffff600160381b820416938201939093526001600160a01b03600160481b8404811660608301908152968a9052949093526001600160e81b031990911690559151163314611c9857806060015133604051638e30e82360e01b8152600401610a52929190615af1565b8051600090611cce907f00000000000000000000000000000000000000000000000000000000000000009063ffffffff16615b0b565b90506000611cda613715565b90506000836020015162ffffff1682611cf3919061535c565b9050808310611d385782846020015162ffffff1684611d129190615ade565b611d1d906001615ade565b6040516315ad27c360e01b8152600401610a52929190615758565b6001600160401b03831115611d63576040516302c6ef8160e11b815260048101849052602401610a52565b604051888152339088907f16f3f633197fafab10a5df69e6f3f2f7f20092f08d8d47de0a91c0f4b96a1a259060200160405180910390a3611dc68785600d6000611db1888a6020015161379f565b815260200190815260200160002054866137ae565b98975050505050505050565b600454610100900460ff1615611dfb5760405163769dd35360e11b815260040160405180910390fd5b6000818152600760205260409020546001600160a01b0316611e335760405163c5171ee960e01b815260048101829052602401610a52565b6000818152600760205260409020600101546001600160a01b03163314611e8a576000818152600760205260409081902060010154905163d084e97560e01b8152610a52916001600160a01b031690600401614e5b565b6000818152600760205260409081902080546001600160a01b031980821633908117845560019093018054909116905591516001600160a01b039092169183917fd4114ab6e9af9f597c52041f32d62dc57c5c4e4c0d4427006069635e216c938691611ef7918591615af1565b60405180910390a25050565b60008281526007602052604090205482906001600160a01b031680611f3e5760405163c5171ee960e01b815260048101839052602401610a52565b336001600160a01b03821614611f695780604051636c51fda960e11b8152600401610a529190614e5b565b600454610100900460ff1615611f925760405163769dd35360e11b815260040160405180910390fd5b60045462010000900460ff1615611fbc5760405163ab35696f60e01b815260040160405180910390fd5b60008481526007602052604090206002015460631901611fef576040516305a48e0f60e01b815260040160405180910390fd5b60036000611ffd8587613967565b815260208101919091526040016000205460ff166120b9576001600360006120258688613967565b815260208082019290925260409081016000908120805460ff191694151594909417909355868352600782528083206002018054600181018255908452919092200180546001600160a01b0319166001600160a01b0386161790555184907f1e980d04aa7648e205713e5e8ea3808672ac163d10936d36f91b2c88ac1575e1906120b0908690614e5b565b60405180910390a25b50505050565b600454610100900460ff16156120e85760405163769dd35360e11b815260040160405180910390fd5b6120f18361346a565b6121105782604051635428d44960e01b8152600401610a529190614e5b565b604081146121355760408051636865567560e01b8152610a5291908390600401615aaa565b600061214382840184615b22565b90506000806000806121588560200151612c21565b9350935093509350816001600160a01b0316336001600160a01b0316146121945781604051636c51fda960e11b8152600401610a529190614e5b565b876001600160a01b031663294daa496040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121f69190615b5c565b60ff16856000015160ff1614612293578460000151886001600160a01b031663294daa496040518163ffffffff1660e01b8152600401602060405180830381865afa158015612249573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061226d9190615b5c565b60405163e7aada9560e01b815260ff928316600482015291166024820152604401610a52565b6001600160401b038316156122bb57604051631685ecdd60e31b815260040160405180910390fd5b60006040518060a001604052806122d0600190565b60ff16815260200187602001518152602001846001600160a01b03168152602001838152602001866001600160601b031681525090506000816040516020016123199190615b79565b60405160208183030381529060405290506123378760200151612ff4565b600280548791906000906123559084906001600160601b031661539e565b92506101000a8154816001600160601b0302191690836001600160601b031602179055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb8b886040518363ffffffff1660e01b81526004016123c79291906153fb565b6020604051808303816000875af11580156123e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061240a91906153de565b61244b5760405162461bcd60e51b8152602060048201526012602482015271696e73756666696369656e742066756e647360701b6044820152606401610a52565b60405163ce3f471960e01b81526001600160a01b038b169063ce3f471990612477908490600401615c25565b600060405180830381600087803b15801561249157600080fd5b505af11580156124a5573d6000803e3d6000fd5b50506004805461ff00191661010017905550600090505b835181101561254f578381815181106124d7576124d7615330565b60200260200101516001600160a01b0316638ea981178c6040518263ffffffff1660e01b815260040161250a9190614e5b565b600060405180830381600087803b15801561252457600080fd5b505af1158015612538573d6000803e3d6000fd5b50505050808061254790615385565b9150506124bc565b506004805461ff00191690556020870151875160405160ff909116907fbd89b747474d3fc04664dfbd1d56ae7ffbe46ee097cdb9979c13916bb76269ce90612598908e90614e5b565b60405180910390a350505050505050505050565b60008281526007602052604090205482906001600160a01b0316806125e75760405163c5171ee960e01b815260048101839052602401610a52565b336001600160a01b038216146126125780604051636c51fda960e11b8152600401610a529190614e5b565b600454610100900460ff161561263b5760405163769dd35360e11b815260040160405180910390fd5b600084815260086020526040902054600160601b90046001600160401b03161561267857604051631685ecdd60e31b815260040160405180910390fd5b600360006126868587613967565b815260208101919091526040016000205460ff166126bb5783836040516379bfd40160e01b8152600401610a52929190615c38565b60008481526007602090815260408083206002018054825181850281018501909352808352919290919083018282801561271e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612700575b50505050509050600060018251612735919061535c565b905060005b825181101561284057856001600160a01b031683828151811061275f5761275f615330565b60200260200101516001600160a01b03160361282e57600083838151811061278957612789615330565b6020026020010151905080600760008a815260200190815260200160002060020183815481106127bb576127bb615330565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394909416939093179092558981526007909152604090206002018054806128065761280661536f565b600082815260209020810160001990810180546001600160a01b031916905501905550612840565b8061283881615385565b91505061273a565b506003600061284f8789613967565b815260208101919091526040908101600020805460ff191690555186907f32158c6058347c1601b2d12bc696ac6901d8a9a9aa3ba10c27ab0a983e8425a790611bbe908890614e5b565b604051632cb6686f60e01b815260040160405180910390fd5b60008281526007602052604090205482906001600160a01b0316806128ed5760405163c5171ee960e01b815260048101839052602401610a52565b336001600160a01b038216146129185780604051636c51fda960e11b8152600401610a529190614e5b565b600454610100900460ff16156129415760405163769dd35360e11b815260040160405180910390fd5b6000848152600760205260409020600101546001600160a01b038481169116146120b9576000848152600760205260409081902060010180546001600160a01b0319166001600160a01b0386161790555184907f21a4dad170a6bf476c31bbcf4a16628295b0e450672eec25d7c93308e05344a1906120b09033908790615af1565b60045460009062010000900460ff16156129f05760405163ab35696f60e01b815260040160405180910390fd5b600454610100900460ff1615612a195760405163769dd35360e11b815260040160405180910390fd5b3415612a3a57604051630b829bad60e21b8152346004820152602401610a52565b600080612a4989338a8a613143565b925050915060006040518061010001604052808481526020018a61ffff168152602001336001600160a01b031681526020018781526020018863ffffffff166001600160601b031681526020018b81526020016000815260200160008152509050600080612ab68361397d565b60c087019190915260e08601919091526040519193509150612ae29085908c908f908790602001615c4f565b60405160208183030381529060405280519060200120600c6000878152602001908152602001600020819055506000604051806101600160405280878152602001336001600160a01b03168152602001866001600160401b031681526020018c62ffffff1681526020018e81526020018d61ffff1681526020018b63ffffffff1681526020018581526020018a8152602001848152602001836001600160601b0316815250905080600001517f01872fb9c7d6d68af06a17347935e04412da302a377224c205e672c26e18c37f82602001518360400151846060015185608001518660a001518760c001518860e0015160c001518960e0015160e001518a61010001518b61012001518c6101400151604051612c089b9a99989796959493929190615d02565b60405180910390a250939b9a5050505050505050505050565b600081815260076020526040812054819081906060906001600160a01b0316612c605760405163c5171ee960e01b815260048101869052602401610a52565b60008581526008602090815260408083205460078352928190208054600290910180548351818602810186019094528084526001600160601b03861695600160601b90046001600160401b0316946001600160a01b03909316939192839190830182828015612cf857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612cda575b5050505050905093509350935093509193509193565b612d16612f9f565b610a5b81613bb4565b600a546001600160a01b03163314612d4a57604051634bea32db60e11b815260040160405180910390fd5b60405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90612d9890859085906004016153c5565b6020604051808303816000875af1158015612db7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ddb91906153de565b611678576040516370a0823160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190612e2b903090600401614e5b565b602060405180830381865afa158015612e48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6c9190615d98565b8160405163cf47918160e01b8152600401610a52929190615758565b604080516101408101825260045460ff80821615158352610100808304821615156020808601919091526201000084048316151585870152630100000084048316606080870191909152600160201b80860490941660808088019190915263ffffffff600160281b8704811660a0890152600160481b8704811660c0890152600160681b8704811660e0890152600160881b9096048616938701939093526005546001600160601b039081166101208801528751938401885260065495861684526001600160401b03948604851692840192909252600160601b850490931695820195909552600160a01b90920490931692810192909252600091612f8d9190613c57565b6001600160601b031690505b92915050565b6000546001600160a01b03163314612ff25760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b6044820152606401610a52565b565b6000818152600760209081526040808320815160608101835281546001600160a01b0390811682526001830154168185015260028201805484518187028101870186528181529295939486019383018282801561307a57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161305c575b505050505081525050905060005b8160400151518110156130ea57600360006130c0846040015184815181106130b2576130b2615330565b602002602001015186613967565b81526020810191909152604001600020805460ff19169055806130e281615385565b915050613088565b50600082815260076020526040812080546001600160a01b031990811682556001820180549091169055906131226002830182614a3e565b505050600090815260086020526040902080546001600160a01b0319169055565b600061314d614a5c565b60006103e88561ffff16111561317c57846103e8604051634a90778560e01b8152600401610a52929190615aaa565b8461ffff166000036131a1576040516308fad2a760e01b815260040160405180910390fd5b6000806131ac613c9d565b600e54919350915065ffffffffffff1660006132178b8b84604080513060208201529081018490526001600160a01b038316606082015265ffffffffffff8216608082015260009060a00160408051601f198184030181529190528051602090910120949350505050565b9050613224826001615db1565b600e805465ffffffffffff9290921665ffffffffffff199092169190911790556040805160808101825263ffffffff909416845262ffffff8916602085015261ffff8a16908401526001600160a01b038a1660608401529550909350909150509450945094915050565b604080516080808201835260065463ffffffff8082168452600160201b8083046001600160401b03908116602080880191909152600160601b850490911686880152600160a01b9093046001600160601b0390811660608088019190915287516101408101895260045460ff808216151583526101008083048216151598840198909852620100008204811615159a83019a909a52630100000081048a169282019290925292810490971694820194909452600160281b8604821660a0820152600160481b8604821660c0820152600160681b8604821660e0820152600160881b9095041690840152600554166101208301526000918291906003836133948888613967565b815260208101919091526040016000205460ff166133c95784866040516379bfd40160e01b8152600401610a52929190615c38565b60006133d58284613c57565b600087815260086020526040902080546001600160601b0392831693509091168281101561342457815460405163cf47918160e01b8152610a52916001600160601b0316908590600401615dd0565b81546001600160601b0319908116918490036001600160601b038181169390931790935560028054918216918316859003909216179055909450925050505b9250929050565b6000805b6009548110156134ca57826001600160a01b03166009828154811061349557613495615330565b6000918252602090912001546001600160a01b0316036134b85750600192915050565b806134c281615385565b91505061346e565b50600092915050565b6000826001600160401b031684600001516001600160401b0316111561352257835160405163012d824d60e01b81526001600160401b0380861660048301529091166024820152604401610a52565b606084015151604080860151905160009161353f91602001615de9565b60405160208183030381529060405280519060200120905085604001516000015160006002811061357257613572615330565b602002015115801561358b575060408601515160200151155b156135c557600d60006135af88600001516001600160401b0316896020015161379f565b8152602001908152602001600020549050613648565b856080015115613648576000600d60006135f089600001516001600160401b03168a6020015161379f565b81526020810191909152604001600020549050806136425781600d60006136288a600001516001600160401b03168b6020015161379f565b815260208101919091526040016000205560019350613646565b8091505b505b6000613655838389613d70565b905083806136605750805b979650505050505050565b60008060008061367b8686614189565b6001600160401b031690506000613693826010615b0b565b9050600060146136a4836015615b0b565b6136ae9190615e29565b89516136ba9190615b0b565b838960e0015163ffffffff168c6136d19190615abe565b6001600160601b03166136e49190615b0b565b6136ee9190615ade565b90506000806137008360008c8c614202565b909d909c50949a509398505050505050505050565b60004661a4b181148061372a575062066eed81145b156137985760646001600160a01b031663a3b1b31d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561376e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137929190615d98565b91505090565b4391505090565b62ffffff1660189190911b1790565b6060826137e05760405163220a34e960e11b8152600481018690526001600160401b0383166024820152604401610a52565b604080516020808201889052865163ffffffff168284015286015162ffffff166060808301919091529186015161ffff166080820152908501516001600160a01b031660a082015260c0810184905260009060e0016040516020818303038152906040528051906020012090506103e8856040015161ffff1611156138825784604001516103e8604051634a90778560e01b8152600401610a52929190615aaa565b6000856040015161ffff166001600160401b038111156138a4576138a4614b68565b6040519080825280602002602001820160405280156138cd578160200160208202803683370190505b50905060005b866040015161ffff168161ffff16101561395c57828160405160200161391092919091825260f01b6001600160f01b031916602082015260220190565b6040516020818303038152906040528051906020012060001c828261ffff168151811061393f5761393f615330565b602090810291909101015280613954816159d0565b9150506138d3565b509695505050505050565b60a081901b6001600160a01b0383161792915050565b6000806000806003600061399987604001518860a00151613967565b815260208101919091526040016000205460ff166139d6578460a0015185604001516040516379bfd40160e01b8152600401610a52929190615c38565b604080516080808201835260065463ffffffff80821684526001600160401b03600160201b8084048216602080880191909152600160601b8504909216868801526001600160601b03600160a01b909404841660608088019190915287516101408101895260045460ff808216151583526101008083048216151596840196909652620100008204811615159a83019a909a52630100000081048a168284015292830490981688870152600160281b8204841660a0890152600160481b8204841660c0890152600160681b8204841660e0890152600160881b90910490921690860152600554909116610120850152908801519088015191929160009182918291613ae291868861366b565b60a08d0151600090815260086020526040902080546001600160601b0394851697509295509093509116841115613b3a57805460405163cf47918160e01b8152610a52916001600160601b0316908690600401615dd0565b80546001600160601b0360016001600160401b03600160601b8085048216929092011602818116828416178790038083166001600160601b03199283166001600160a01b03199095169490941793909317909355600280548083168890039092169190931617909155929a91995097509095509350505050565b336001600160a01b03821603613c065760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103a3930b739b332b9103a379039b2b63360491b6044820152606401610a52565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600080613c648484614189565b8460c0015163ffffffff16613c799190615e3d565b6001600160401b031690506000613c938260008787614202565b5095945050505050565b6000806000613caa613715565b90506000613cd87f000000000000000000000000000000000000000000000000000000000000000083615e60565b9050600081613d077f000000000000000000000000000000000000000000000000000000000000000085615ade565b613d11919061535c565b90506000613d3f7f000000000000000000000000000000000000000000000000000000000000000083615e29565b905063ffffffff8110613d65576040516307b2a52360e41b815260040160405180910390fd5b909590945092505050565b6000806040518060c00160405280866001600160401b03811115613d9657613d96614b68565b604051908082528060200260200182016040528015613dbf578160200160208202803683370190505b508152602001866001600160401b03811115613ddd57613ddd614b68565b6040519080825280601f01601f191660200182016040528015613e07576020820181803683370190505b508152602001866001600160401b03811115613e2557613e25614b68565b604051908082528060200260200182016040528015613e5857816020015b6060815260200190600190039081613e435790505b50815260006020820152604001866001600160401b03811115613e7d57613e7d614b68565b604051908082528060200260200182016040528015613ea6578160200160208202803683370190505b508152602001866001600160401b03811115613ec457613ec4614b68565b604051908082528060200260200182016040528015613eed578160200160208202803683370190505b509052905060005b8581101561406c57600084606001518281518110613f1557613f15615330565b60200260200101519050600080600080613f3989600001518a602001518c8861424d565b93509350935093508315613f8d57828760400151886060015161ffff1681518110613f6657613f66615330565b602090810291909101015260608701805190613f81826159d0565b61ffff16905250613fc0565b600160f81b87602001518781518110613fa857613fa8615330565b60200101906001600160f81b031916908160001a9053505b8780613fca575080155b85515188518051929a50909188908110613fe657613fe6615330565b602002602001018181525050818760800151878151811061400957614009615330565b60200260200101906001600160601b031690816001600160601b031681525050846000015160a001518760a00151878151811061404857614048615330565b6020026020010181815250505050505050808061406490615385565b915050613ef5565b5060608301515115614181576000816060015161ffff166001600160401b0381111561409a5761409a614b68565b6040519080825280602002602001820160405280156140cd57816020015b60608152602001906001900390816140b85790505b50905060005b826060015161ffff1681101561413157826040015181815181106140f9576140f9615330565b602002602001015182828151811061411357614113615330565b6020026020010181905250808061412990615385565b9150506140d3565b5081516020830151608084015160a08501516040517f8f79f730779e875ce76c428039cc2052b5b5918c2a55c598fab251c1198aec549461417794909390928792615ead565b60405180910390a1505b509392505050565b815160009080156141a6575060408201516001600160401b031615155b156141fa5761010083015163ffffffff16431080806141e757506101008401516141d69063ffffffff164361535c565b83602001516001600160401b031610155b156141f85750506040810151612f99565b505b503a92915050565b600080600060648560600151606461421a9190615f50565b6142279060ff1689615b0b565b6142319190615e29565b905061423f818787876145bc565b925092505094509492505050565b805160a09081015160009081526008602090815260408083208551948501519151939460609486948594859261428b928e928e929091879101615c4f565b60408051601f19818403018152918152815160209283012084516000908152600c90935291205490915081146142fe5750505460408051808201909152601081526f756e6b6e6f776e2063616c6c6261636b60801b60208201526001955093506001600160601b031691508390506145b1565b50614307614a5c565b600061433c7f00000000000000000000000000000000000000000000000000000000000000006001600160401b038e16615e29565b6040805160808101825263ffffffff909216825262ffffff8d1660208084019190915285015161ffff16828201528401516001600160a01b0316606082015291508990506143d0575050604080518082019091526016815275756e617661696c61626c652072616e646f6d6e65737360501b60208201529054600195509093506001600160601b03169150600090506145b1565b60006143e28360000151838c8f6137ae565b606080840151855191860151604051939450909260009263d21ea8fd60e01b9261441192879190602401615f69565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526004805461ff00191661010017905590506000805a9050600061447c8e60000151608001516001600160601b0316896040015186614630565b9093509050806144b1578d516080015160405163aad1598360e01b8152610a52916001600160601b0316908490600401615758565b506000610bb85a6144c29190615ade565b6004805461ff00191690559050818110156144eb576144eb6144e4828461535c565b8f5161466f565b8854600160601b90046001600160401b031689600c61450983615f94565b82546001600160401b039182166101009390930a92830291909202199091161790555087516000908152600c60205260408120558261457f5760408051808201909152601081526f195e1958dd5d1a5bdb8819985a5b195960821b60208201528954600191906001600160601b0316600061459f565b604080516020810190915260008082528a549091906001600160601b0316825b9c509c509c509c505050505050505050505b945094509450949050565b6000808085156145cc57856145d6565b6145d6858561489b565b90506000816145ed89670de0b6b3a7640000615b0b565b6145f79190615e29565b9050676765c793fa10079d601b1b8111156146245760405162de437160e81b815260040160405180910390fd5b97909650945050505050565b6000805a610bb8811061466657610bb881039050856040820482031115614666576000808551602087016000898bf19250600191505b50935093915050565b80608001516001600160601b0316821115614688575050565b6004546000906064906146a590600160201b900460ff1682615fb7565b60ff168360c001518585608001516001600160601b03166146c6919061535c565b6146d09190615b0b565b6146da9190615b0b565b6146e49190615e29565b60e080840151604080516101408101825260045460ff80821615158352610100808304821615156020808601919091526201000084048316151585870152630100000084048316606080870191909152600160201b80860490941660808088019190915263ffffffff600160281b8704811660a0890152600160481b8704811660c0890152600160681b870481169a88019a909a52600160881b9095048916928601929092526005546001600160601b039081166101208701528651948501875260065498891685526001600160401b03938904841691850191909152600160601b880490921694830194909452600160a01b909504909416918401919091529293506000926147f792859291906145bc565b5060a08401516000908152600860205260408120805492935083929091906148299084906001600160601b0316615abe565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600260008282829054906101000a90046001600160601b03166148719190615abe565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555050505050565b60a0820151606082015160009190600163ffffffff831611908180156148d7575084516148ce9063ffffffff164261535c565b8363ffffffff16105b156148e457506101208501515b6001600160601b031695945050505050565b604051806080016040528060006001600160401b03168152602001600062ffffff16815260200160008152602001600081525090565b6040518061010001604052806008906020820280368337509192915050565b6001830191839082156149d95791602002820160005b838211156149a857833562ffffff1683826101000a81548162ffffff021916908362ffffff1602179055509260200192600301602081600201049283019260010302614961565b80156149d75782816101000a81549062ffffff02191690556003016020816002010492830192600103026149a8565b505b506149e5929150614a83565b5090565b8280548282559060005260206000209081019282156149d9579160200282015b828111156149d957825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190614a09565b5080546000825590600052602060002090810190610a5b9190614a83565b60408051608081018252600080825260208201819052918101829052606081019190915290565b5b808211156149e55760008155600101614a84565b6001600160a01b0381168114610a5b57600080fd5b8035614ab881614a98565b919050565b600060208284031215614acf57600080fd5b8135614ada81614a98565b9392505050565b60008060408385031215614af457600080fd5b823591506020830135614b0681614a98565b809150509250929050565b600060208284031215614b2357600080fd5b5035919050565b60006101408284031215614b3d57600080fd5b50919050565b803561ffff81168114614ab857600080fd5b803562ffffff81168114614ab857600080fd5b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715614ba057614ba0614b68565b60405290565b60405161010081016001600160401b0381118282101715614ba057614ba0614b68565b60405160a081016001600160401b0381118282101715614ba057614ba0614b68565b604051602081016001600160401b0381118282101715614ba057614ba0614b68565b604051601f8201601f191681016001600160401b0381118282101715614c3557614c35614b68565b604052919050565b600082601f830112614c4e57600080fd5b81356001600160401b03811115614c6757614c67614b68565b614c7a601f8201601f1916602001614c0d565b818152846020838601011115614c8f57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215614cc257600080fd5b84359350614cd260208601614b43565b9250614ce060408601614b55565b915060608501356001600160401b03811115614cfb57600080fd5b614d0787828801614c3d565b91505092959194509250565b60008083601f840112614d2557600080fd5b5081356001600160401b03811115614d3c57600080fd5b6020830191508360208260051b850101111561346357600080fd5b60008060008060408587031215614d6d57600080fd5b84356001600160401b0380821115614d8457600080fd5b614d9088838901614d13565b90965094506020870135915080821115614da957600080fd5b50614db687828801614d13565b95989497509550505050565b80356001600160401b0381168114614ab857600080fd5b600080600080600060808688031215614df157600080fd5b85356001600160401b03811115614e0757600080fd5b614e1388828901614d13565b90965094505060208601356001600160c01b0381168114614e3357600080fd5b9250614e4160408701614dc2565b9150614e4f60608701614dc2565b90509295509295909350565b6001600160a01b0391909116815260200190565b6101008101818360005b6008811015614e9d57815162ffffff16835260209283019290910190600101614e79565b50505092915050565b63ffffffff81168114610a5b57600080fd5b8035614ab881614ea6565b600060408284031215614ed557600080fd5b614edd614b7e565b8235614ee881614ea6565b81526020830135614ef881614ea6565b60208201529392505050565b8015158114610a5b57600080fd5b8035614ab881614f04565b600060208284031215614f2f57600080fd5b8135614ada81614f04565b6000610100808385031215614f4e57600080fd5b838184011115614f5d57600080fd5b509092915050565b60008060008060808587031215614f7b57600080fd5b843593506020850135614f8d81614ea6565b925060408501356001600160401b0380821115614fa957600080fd5b614fb588838901614c3d565b93506060870135915080821115614fcb57600080fd5b50614d0787828801614c3d565b60008083601f840112614fea57600080fd5b5081356001600160401b0381111561500157600080fd5b60208301915083602082850101111561346357600080fd5b6000806000806060858703121561502f57600080fd5b843561503a81614a98565b93506020850135925060408501356001600160401b0381111561505c57600080fd5b614db687828801614fd8565b60008060006060848603121561507d57600080fd5b833592506020840135915060408401356001600160401b038111156150a157600080fd5b6150ad86828701614c3d565b9150509250925092565b600081518084526020808501945080840160005b838110156150e7578151875295820195908201906001016150cb565b509495945050505050565b602081526000614ada60208301846150b7565b60008060006040848603121561511a57600080fd5b833561512581614a98565b925060208401356001600160401b0381111561514057600080fd5b61514c86828701614fd8565b9497909650939450505050565b6000806020838503121561516c57600080fd5b82356001600160401b0381111561518257600080fd5b61518e85828601614fd8565b90969095509350505050565b60008060008060008060c087890312156151b357600080fd5b863595506151c360208801614b43565b94506151d160408801614b55565b935060608701356151e181614ea6565b925060808701356001600160401b03808211156151fd57600080fd5b6152098a838b01614c3d565b935060a089013591508082111561521f57600080fd5b5061522c89828a01614c3d565b9150509295509295509295565b600081518084526020808501945080840160005b838110156150e75781516001600160a01b03168752958201959082019060010161524d565b6001600160601b03851681526001600160401b03841660208201526001600160a01b03831660408201526080606082018190526000906152b490830184615239565b9695505050505050565b600080604083850312156152d157600080fd5b82356152dc81614a98565b946020939093013593505050565b600080604083850312156152fd57600080fd5b8235915060208301356001600160401b0381111561531a57600080fd5b61532685828601614c3d565b9150509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b81810381811115612f9957612f99615346565b634e487b7160e01b600052603160045260246000fd5b60006001820161539757615397615346565b5060010190565b6001600160601b038281168282160390808211156153be576153be615346565b5092915050565b6001600160a01b03929092168252602082015260400190565b6000602082840312156153f057600080fd5b8151614ada81614f04565b6001600160a01b039290921682526001600160601b0316602082015260400190565b60ff81168114610a5b57600080fd5b8035614ab88161541d565b60006020828403121561544957600080fd5b8135614ada8161541d565b60008135612f9981614f04565b60008135612f998161541d565b60008135612f9981614ea6565b6001600160601b0381168114610a5b57600080fd5b60008135612f998161547b565b81356154a881614f04565b815490151560ff1660ff19919091161781556154e36154c960208401615454565b82805461ff00191691151560081b61ff0016919091179055565b61550e6154f260408401615454565b82805462ff0000191691151560101b62ff000016919091179055565b61553761551d60608401615461565b825463ff000000191660189190911b63ff00000016178255565b61556461554660808401615461565b82805460ff60201b191660209290921b60ff60201b16919091179055565b61559761557360a0840161546e565b82805463ffffffff60281b191660289290921b63ffffffff60281b16919091179055565b6155ca6155a660c0840161546e565b82805463ffffffff60481b191660489290921b63ffffffff60481b16919091179055565b6155fd6155d960e0840161546e565b82805463ffffffff60681b191660689290921b63ffffffff60681b16919091179055565b61563161560d610100840161546e565b82805463ffffffff60881b191660889290921b63ffffffff60881b16919091179055565b6116786156416101208401615490565b6001830180546001600160601b0319166001600160601b0392909216919091179055565b8035614ab88161547b565b61014081016156888261568285614f12565b15159052565b61569460208401614f12565b151560208301526156a760408401614f12565b151560408301526156ba6060840161542c565b60ff1660608301526156ce6080840161542c565b60ff1660808301526156e260a08401614eb8565b63ffffffff1660a08301526156f960c08401614eb8565b63ffffffff1660c083015261571060e08401614eb8565b63ffffffff1660e0830152610100615729848201614eb8565b63ffffffff1690830152610120615741848201615665565b6001600160601b038116848301525b505092915050565b918252602082015260400190565b6000823560be1983360301811261577c57600080fd5b9190910192915050565b600082601f83011261579757600080fd5b813560206001600160401b03808311156157b3576157b3614b68565b8260051b6157c2838201614c0d565b93845285810183019383810190888611156157dc57600080fd5b84880192505b85831015611dc6578235848111156157f957600080fd5b8801601f196040828c038201121561581057600080fd5b615818614b7e565b878301358781111561582957600080fd5b8301610100818e038401121561583e57600080fd5b615846614ba6565b925088810135835261585a60408201614b43565b8984015261586a60608201614aad565b604084015260808101358881111561588157600080fd5b61588f8e8b83850101614c3d565b6060850152506158a160a08201615665565b608084015260c081013560a084015260e081013560c084015261010081013560e0840152508181526158d560408401615665565b818901528452505091840191908401906157e2565b600081360360c08112156158fd57600080fd5b615905614bc9565b61590e84614dc2565b8152602061591d818601614b55565b828201526040603f198401121561593357600080fd5b61593b614beb565b925036605f86011261594c57600080fd5b615954614b7e565b80608087013681111561596657600080fd5b604088015b81811015615982578035845292840192840161596b565b50908552604084019490945250509035906001600160401b038211156159a757600080fd5b6159b336838601615786565b60608201526159c460a08501614f12565b60808201529392505050565b600061ffff8083168181036159e7576159e7615346565b6001019392505050565b6000608080830160018060401b038089168552602060018060c01b038916818701526040828916818801526060858189015284895180875260a08a019150848b01965060005b81811015615a735787518051881684528681015162ffffff16878501528581015186850152840151848401529685019691880191600101615a37565b50909d9c50505050505050505050505050565b60006001600160401b038281166002600160401b031981016159e7576159e7615346565b61ffff929092168252602082015260400190565b6001600160601b038181168382160190808211156153be576153be615346565b80820180821115612f9957612f99615346565b6001600160a01b0392831681529116602082015260400190565b8082028115828204841417612f9957612f99615346565b600060408284031215615b3457600080fd5b615b3c614b7e565b8235615b478161541d565b81526020928301359281019290925250919050565b600060208284031215615b6e57600080fd5b8151614ada8161541d565b6020815260ff82511660208201526020820151604082015260018060a01b0360408301511660608201526000606083015160a06080840152615bbe60c0840182615239565b608094909401516001600160601b031660a093909301929092525090919050565b6000815180845260005b81811015615c0557602081850181015186830182015201615be9565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000614ada6020830184615bdf565b9182526001600160a01b0316602082015260400190565b60018060401b038516815262ffffff84166020820152826040820152608060608201528151608082015261ffff60208301511660a082015260018060a01b0360408301511660c0820152600060608301516101008060e0850152615cb7610180850183615bdf565b91506080850151615cd2828601826001600160601b03169052565b505060a084015161012084015260c084015161014084015260e08401516101608401528091505095945050505050565b6001600160a01b038c1681526001600160401b038b16602082015262ffffff8a1660408201526060810189905261ffff8816608082015263ffffffff871660a082015260c0810186905260e081018590526101606101008201819052600090615d6d83820187615bdf565b61012084019590955250506001600160601b0391909116610140909101529998505050505050505050565b600060208284031215615daa57600080fd5b5051919050565b65ffffffffffff8181168382160190808211156153be576153be615346565b6001600160601b03929092168252602082015260400190565b815160408201908260005b6002811015614e9d578251825260209283019290910190600101615df4565b634e487b7160e01b600052601260045260246000fd5b600082615e3857615e38615e13565b500490565b6001600160401b0381811683821602808216919082811461575057615750615346565b600082615e6f57615e6f615e13565b500690565b600081518084526020808501945080840160005b838110156150e75781516001600160601b031687529582019590820190600101615e88565b60a081526000615ec060a08301886150b7565b602083820381850152615ed38289615bdf565b915083820360408501528187518084528284019150828160051b850101838a0160005b83811015615f2457601f19878403018552615f12838351615bdf565b94860194925090850190600101615ef6565b50508681036060880152615f38818a615e74565b9450505050508281036080840152611dc681856150b7565b60ff8181168382160190811115612f9957612f99615346565b838152606060208201526000615f8260608301856150b7565b82810360408401526152b48185615bdf565b60006001600160401b03821680615fad57615fad615346565b6000190192915050565b60ff8281168282160390811115612f9957612f9961534656fea164736f6c6343000813000a", +} + +var VRFCoordinatorABI = VRFCoordinatorMetaData.ABI + +var VRFCoordinatorBin = VRFCoordinatorMetaData.Bin + +func DeployVRFCoordinator(auth *bind.TransactOpts, backend bind.ContractBackend, beaconPeriodBlocksArg *big.Int, linkToken common.Address) (common.Address, *types.Transaction, *VRFCoordinator, error) { + parsed, err := VRFCoordinatorMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(VRFCoordinatorBin), backend, beaconPeriodBlocksArg, linkToken) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &VRFCoordinator{VRFCoordinatorCaller: VRFCoordinatorCaller{contract: contract}, VRFCoordinatorTransactor: VRFCoordinatorTransactor{contract: contract}, VRFCoordinatorFilterer: VRFCoordinatorFilterer{contract: contract}}, nil +} + +type VRFCoordinator struct { + address common.Address + abi abi.ABI + VRFCoordinatorCaller + VRFCoordinatorTransactor + VRFCoordinatorFilterer +} + +type VRFCoordinatorCaller struct { + contract *bind.BoundContract +} + +type VRFCoordinatorTransactor struct { + contract *bind.BoundContract +} + +type VRFCoordinatorFilterer struct { + contract *bind.BoundContract +} + +type VRFCoordinatorSession struct { + Contract *VRFCoordinator + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type VRFCoordinatorCallerSession struct { + Contract *VRFCoordinatorCaller + CallOpts bind.CallOpts +} + +type VRFCoordinatorTransactorSession struct { + Contract *VRFCoordinatorTransactor + TransactOpts bind.TransactOpts +} + +type VRFCoordinatorRaw struct { + Contract *VRFCoordinator +} + +type VRFCoordinatorCallerRaw struct { + Contract *VRFCoordinatorCaller +} + +type VRFCoordinatorTransactorRaw struct { + Contract *VRFCoordinatorTransactor +} + +func NewVRFCoordinator(address common.Address, backend bind.ContractBackend) (*VRFCoordinator, error) { + abi, err := abi.JSON(strings.NewReader(VRFCoordinatorABI)) + if err != nil { + return nil, err + } + contract, err := bindVRFCoordinator(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &VRFCoordinator{address: address, abi: abi, VRFCoordinatorCaller: VRFCoordinatorCaller{contract: contract}, VRFCoordinatorTransactor: VRFCoordinatorTransactor{contract: contract}, VRFCoordinatorFilterer: VRFCoordinatorFilterer{contract: contract}}, nil +} + +func NewVRFCoordinatorCaller(address common.Address, caller bind.ContractCaller) (*VRFCoordinatorCaller, error) { + contract, err := bindVRFCoordinator(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &VRFCoordinatorCaller{contract: contract}, nil +} + +func NewVRFCoordinatorTransactor(address common.Address, transactor bind.ContractTransactor) (*VRFCoordinatorTransactor, error) { + contract, err := bindVRFCoordinator(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &VRFCoordinatorTransactor{contract: contract}, nil +} + +func NewVRFCoordinatorFilterer(address common.Address, filterer bind.ContractFilterer) (*VRFCoordinatorFilterer, error) { + contract, err := bindVRFCoordinator(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &VRFCoordinatorFilterer{contract: contract}, nil +} + +func bindVRFCoordinator(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := VRFCoordinatorMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_VRFCoordinator *VRFCoordinatorRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _VRFCoordinator.Contract.VRFCoordinatorCaller.contract.Call(opts, result, method, params...) +} + +func (_VRFCoordinator *VRFCoordinatorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFCoordinator.Contract.VRFCoordinatorTransactor.contract.Transfer(opts) +} + +func (_VRFCoordinator *VRFCoordinatorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _VRFCoordinator.Contract.VRFCoordinatorTransactor.contract.Transact(opts, method, params...) +} + +func (_VRFCoordinator *VRFCoordinatorCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _VRFCoordinator.Contract.contract.Call(opts, result, method, params...) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFCoordinator.Contract.contract.Transfer(opts) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _VRFCoordinator.Contract.contract.Transact(opts, method, params...) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) MAXCONSUMERS(opts *bind.CallOpts) (uint16, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "MAX_CONSUMERS") + + if err != nil { + return *new(uint16), err + } + + out0 := *abi.ConvertType(out[0], new(uint16)).(*uint16) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) MAXCONSUMERS() (uint16, error) { + return _VRFCoordinator.Contract.MAXCONSUMERS(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) MAXCONSUMERS() (uint16, error) { + return _VRFCoordinator.Contract.MAXCONSUMERS(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) MAXNUMWORDS(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "MAX_NUM_WORDS") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) MAXNUMWORDS() (*big.Int, error) { + return _VRFCoordinator.Contract.MAXNUMWORDS(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) MAXNUMWORDS() (*big.Int, error) { + return _VRFCoordinator.Contract.MAXNUMWORDS(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) NUMCONFDELAYS(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "NUM_CONF_DELAYS") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) NUMCONFDELAYS() (uint8, error) { + return _VRFCoordinator.Contract.NUMCONFDELAYS(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) NUMCONFDELAYS() (uint8, error) { + return _VRFCoordinator.Contract.NUMCONFDELAYS(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) GetCallbackMemo(opts *bind.CallOpts, requestId *big.Int) ([32]byte, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "getCallbackMemo", requestId) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) GetCallbackMemo(requestId *big.Int) ([32]byte, error) { + return _VRFCoordinator.Contract.GetCallbackMemo(&_VRFCoordinator.CallOpts, requestId) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) GetCallbackMemo(requestId *big.Int) ([32]byte, error) { + return _VRFCoordinator.Contract.GetCallbackMemo(&_VRFCoordinator.CallOpts, requestId) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) GetConfirmationDelays(opts *bind.CallOpts) ([8]*big.Int, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "getConfirmationDelays") + + if err != nil { + return *new([8]*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new([8]*big.Int)).(*[8]*big.Int) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) GetConfirmationDelays() ([8]*big.Int, error) { + return _VRFCoordinator.Contract.GetConfirmationDelays(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) GetConfirmationDelays() ([8]*big.Int, error) { + return _VRFCoordinator.Contract.GetConfirmationDelays(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) GetFee(opts *bind.CallOpts, arg0 *big.Int, arg1 []byte) (*big.Int, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "getFee", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) GetFee(arg0 *big.Int, arg1 []byte) (*big.Int, error) { + return _VRFCoordinator.Contract.GetFee(&_VRFCoordinator.CallOpts, arg0, arg1) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) GetFee(arg0 *big.Int, arg1 []byte) (*big.Int, error) { + return _VRFCoordinator.Contract.GetFee(&_VRFCoordinator.CallOpts, arg0, arg1) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) GetFulfillmentFee(opts *bind.CallOpts, arg0 *big.Int, callbackGasLimit uint32, arguments []byte, arg3 []byte) (*big.Int, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "getFulfillmentFee", arg0, callbackGasLimit, arguments, arg3) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) GetFulfillmentFee(arg0 *big.Int, callbackGasLimit uint32, arguments []byte, arg3 []byte) (*big.Int, error) { + return _VRFCoordinator.Contract.GetFulfillmentFee(&_VRFCoordinator.CallOpts, arg0, callbackGasLimit, arguments, arg3) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) GetFulfillmentFee(arg0 *big.Int, callbackGasLimit uint32, arguments []byte, arg3 []byte) (*big.Int, error) { + return _VRFCoordinator.Contract.GetFulfillmentFee(&_VRFCoordinator.CallOpts, arg0, callbackGasLimit, arguments, arg3) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) GetSubscription(opts *bind.CallOpts, subId *big.Int) (GetSubscription, + + error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "getSubscription", subId) + + outstruct := new(GetSubscription) + if err != nil { + return *outstruct, err + } + + outstruct.Balance = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.PendingFulfillments = *abi.ConvertType(out[1], new(uint64)).(*uint64) + outstruct.Owner = *abi.ConvertType(out[2], new(common.Address)).(*common.Address) + outstruct.Consumers = *abi.ConvertType(out[3], new([]common.Address)).(*[]common.Address) + + return *outstruct, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) GetSubscription(subId *big.Int) (GetSubscription, + + error) { + return _VRFCoordinator.Contract.GetSubscription(&_VRFCoordinator.CallOpts, subId) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) GetSubscription(subId *big.Int) (GetSubscription, + + error) { + return _VRFCoordinator.Contract.GetSubscription(&_VRFCoordinator.CallOpts, subId) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) GetSubscriptionLinkBalance(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "getSubscriptionLinkBalance") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) GetSubscriptionLinkBalance() (*big.Int, error) { + return _VRFCoordinator.Contract.GetSubscriptionLinkBalance(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) GetSubscriptionLinkBalance() (*big.Int, error) { + return _VRFCoordinator.Contract.GetSubscriptionLinkBalance(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) IBeaconPeriodBlocks(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "i_beaconPeriodBlocks") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) IBeaconPeriodBlocks() (*big.Int, error) { + return _VRFCoordinator.Contract.IBeaconPeriodBlocks(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) IBeaconPeriodBlocks() (*big.Int, error) { + return _VRFCoordinator.Contract.IBeaconPeriodBlocks(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) ILink(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "i_link") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) ILink() (common.Address, error) { + return _VRFCoordinator.Contract.ILink(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) ILink() (common.Address, error) { + return _VRFCoordinator.Contract.ILink(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) MigrationVersion(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "migrationVersion") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) MigrationVersion() (uint8, error) { + return _VRFCoordinator.Contract.MigrationVersion(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) MigrationVersion() (uint8, error) { + return _VRFCoordinator.Contract.MigrationVersion(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) OnMigration(opts *bind.CallOpts, arg0 []byte) error { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "onMigration", arg0) + + if err != nil { + return err + } + + return err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) OnMigration(arg0 []byte) error { + return _VRFCoordinator.Contract.OnMigration(&_VRFCoordinator.CallOpts, arg0) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) OnMigration(arg0 []byte) error { + return _VRFCoordinator.Contract.OnMigration(&_VRFCoordinator.CallOpts, arg0) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) Owner() (common.Address, error) { + return _VRFCoordinator.Contract.Owner(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) Owner() (common.Address, error) { + return _VRFCoordinator.Contract.Owner(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) SCallbackConfig(opts *bind.CallOpts) (SCallbackConfig, + + error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "s_callbackConfig") + + outstruct := new(SCallbackConfig) + if err != nil { + return *outstruct, err + } + + outstruct.MaxCallbackGasLimit = *abi.ConvertType(out[0], new(uint32)).(*uint32) + outstruct.MaxCallbackArgumentsLength = *abi.ConvertType(out[1], new(uint32)).(*uint32) + + return *outstruct, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) SCallbackConfig() (SCallbackConfig, + + error) { + return _VRFCoordinator.Contract.SCallbackConfig(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) SCallbackConfig() (SCallbackConfig, + + error) { + return _VRFCoordinator.Contract.SCallbackConfig(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) SCoordinatorConfig(opts *bind.CallOpts) (SCoordinatorConfig, + + error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "s_coordinatorConfig") + + outstruct := new(SCoordinatorConfig) + if err != nil { + return *outstruct, err + } + + outstruct.UseReasonableGasPrice = *abi.ConvertType(out[0], new(bool)).(*bool) + outstruct.ReentrancyLock = *abi.ConvertType(out[1], new(bool)).(*bool) + outstruct.Paused = *abi.ConvertType(out[2], new(bool)).(*bool) + outstruct.PremiumPercentage = *abi.ConvertType(out[3], new(uint8)).(*uint8) + outstruct.UnusedGasPenaltyPercent = *abi.ConvertType(out[4], new(uint8)).(*uint8) + outstruct.StalenessSeconds = *abi.ConvertType(out[5], new(uint32)).(*uint32) + outstruct.RedeemableRequestGasOverhead = *abi.ConvertType(out[6], new(uint32)).(*uint32) + outstruct.CallbackRequestGasOverhead = *abi.ConvertType(out[7], new(uint32)).(*uint32) + outstruct.ReasonableGasPriceStalenessBlocks = *abi.ConvertType(out[8], new(uint32)).(*uint32) + outstruct.FallbackWeiPerUnitLink = *abi.ConvertType(out[9], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) SCoordinatorConfig() (SCoordinatorConfig, + + error) { + return _VRFCoordinator.Contract.SCoordinatorConfig(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) SCoordinatorConfig() (SCoordinatorConfig, + + error) { + return _VRFCoordinator.Contract.SCoordinatorConfig(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) SPendingRequests(opts *bind.CallOpts, arg0 *big.Int) (SPendingRequests, + + error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "s_pendingRequests", arg0) + + outstruct := new(SPendingRequests) + if err != nil { + return *outstruct, err + } + + outstruct.SlotNumber = *abi.ConvertType(out[0], new(uint32)).(*uint32) + outstruct.ConfirmationDelay = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + outstruct.NumWords = *abi.ConvertType(out[2], new(uint16)).(*uint16) + outstruct.Requester = *abi.ConvertType(out[3], new(common.Address)).(*common.Address) + + return *outstruct, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) SPendingRequests(arg0 *big.Int) (SPendingRequests, + + error) { + return _VRFCoordinator.Contract.SPendingRequests(&_VRFCoordinator.CallOpts, arg0) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) SPendingRequests(arg0 *big.Int) (SPendingRequests, + + error) { + return _VRFCoordinator.Contract.SPendingRequests(&_VRFCoordinator.CallOpts, arg0) +} + +func (_VRFCoordinator *VRFCoordinatorCaller) SProducer(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFCoordinator.contract.Call(opts, &out, "s_producer") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFCoordinator *VRFCoordinatorSession) SProducer() (common.Address, error) { + return _VRFCoordinator.Contract.SProducer(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorCallerSession) SProducer() (common.Address, error) { + return _VRFCoordinator.Contract.SProducer(&_VRFCoordinator.CallOpts) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "acceptOwnership") +} + +func (_VRFCoordinator *VRFCoordinatorSession) AcceptOwnership() (*types.Transaction, error) { + return _VRFCoordinator.Contract.AcceptOwnership(&_VRFCoordinator.TransactOpts) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _VRFCoordinator.Contract.AcceptOwnership(&_VRFCoordinator.TransactOpts) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) AcceptSubscriptionOwnerTransfer(opts *bind.TransactOpts, subId *big.Int) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "acceptSubscriptionOwnerTransfer", subId) +} + +func (_VRFCoordinator *VRFCoordinatorSession) AcceptSubscriptionOwnerTransfer(subId *big.Int) (*types.Transaction, error) { + return _VRFCoordinator.Contract.AcceptSubscriptionOwnerTransfer(&_VRFCoordinator.TransactOpts, subId) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) AcceptSubscriptionOwnerTransfer(subId *big.Int) (*types.Transaction, error) { + return _VRFCoordinator.Contract.AcceptSubscriptionOwnerTransfer(&_VRFCoordinator.TransactOpts, subId) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) AddConsumer(opts *bind.TransactOpts, subId *big.Int, consumer common.Address) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "addConsumer", subId, consumer) +} + +func (_VRFCoordinator *VRFCoordinatorSession) AddConsumer(subId *big.Int, consumer common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.AddConsumer(&_VRFCoordinator.TransactOpts, subId, consumer) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) AddConsumer(subId *big.Int, consumer common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.AddConsumer(&_VRFCoordinator.TransactOpts, subId, consumer) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) BatchTransferLink(opts *bind.TransactOpts, recipients []common.Address, paymentsInJuels []*big.Int) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "batchTransferLink", recipients, paymentsInJuels) +} + +func (_VRFCoordinator *VRFCoordinatorSession) BatchTransferLink(recipients []common.Address, paymentsInJuels []*big.Int) (*types.Transaction, error) { + return _VRFCoordinator.Contract.BatchTransferLink(&_VRFCoordinator.TransactOpts, recipients, paymentsInJuels) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) BatchTransferLink(recipients []common.Address, paymentsInJuels []*big.Int) (*types.Transaction, error) { + return _VRFCoordinator.Contract.BatchTransferLink(&_VRFCoordinator.TransactOpts, recipients, paymentsInJuels) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) CancelSubscription(opts *bind.TransactOpts, subId *big.Int, to common.Address) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "cancelSubscription", subId, to) +} + +func (_VRFCoordinator *VRFCoordinatorSession) CancelSubscription(subId *big.Int, to common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.CancelSubscription(&_VRFCoordinator.TransactOpts, subId, to) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) CancelSubscription(subId *big.Int, to common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.CancelSubscription(&_VRFCoordinator.TransactOpts, subId, to) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) CreateSubscription(opts *bind.TransactOpts) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "createSubscription") +} + +func (_VRFCoordinator *VRFCoordinatorSession) CreateSubscription() (*types.Transaction, error) { + return _VRFCoordinator.Contract.CreateSubscription(&_VRFCoordinator.TransactOpts) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) CreateSubscription() (*types.Transaction, error) { + return _VRFCoordinator.Contract.CreateSubscription(&_VRFCoordinator.TransactOpts) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) DeregisterMigratableCoordinator(opts *bind.TransactOpts, target common.Address) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "deregisterMigratableCoordinator", target) +} + +func (_VRFCoordinator *VRFCoordinatorSession) DeregisterMigratableCoordinator(target common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.DeregisterMigratableCoordinator(&_VRFCoordinator.TransactOpts, target) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) DeregisterMigratableCoordinator(target common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.DeregisterMigratableCoordinator(&_VRFCoordinator.TransactOpts, target) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) Migrate(opts *bind.TransactOpts, newCoordinator common.Address, encodedRequest []byte) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "migrate", newCoordinator, encodedRequest) +} + +func (_VRFCoordinator *VRFCoordinatorSession) Migrate(newCoordinator common.Address, encodedRequest []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.Migrate(&_VRFCoordinator.TransactOpts, newCoordinator, encodedRequest) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) Migrate(newCoordinator common.Address, encodedRequest []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.Migrate(&_VRFCoordinator.TransactOpts, newCoordinator, encodedRequest) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) OnTokenTransfer(opts *bind.TransactOpts, arg0 common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "onTokenTransfer", arg0, amount, data) +} + +func (_VRFCoordinator *VRFCoordinatorSession) OnTokenTransfer(arg0 common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.OnTokenTransfer(&_VRFCoordinator.TransactOpts, arg0, amount, data) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) OnTokenTransfer(arg0 common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.OnTokenTransfer(&_VRFCoordinator.TransactOpts, arg0, amount, data) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) ProcessVRFOutputs(opts *bind.TransactOpts, vrfOutputs []VRFBeaconTypesVRFOutput, juelsPerFeeCoin *big.Int, reasonableGasPrice uint64, blockHeight uint64) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "processVRFOutputs", vrfOutputs, juelsPerFeeCoin, reasonableGasPrice, blockHeight) +} + +func (_VRFCoordinator *VRFCoordinatorSession) ProcessVRFOutputs(vrfOutputs []VRFBeaconTypesVRFOutput, juelsPerFeeCoin *big.Int, reasonableGasPrice uint64, blockHeight uint64) (*types.Transaction, error) { + return _VRFCoordinator.Contract.ProcessVRFOutputs(&_VRFCoordinator.TransactOpts, vrfOutputs, juelsPerFeeCoin, reasonableGasPrice, blockHeight) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) ProcessVRFOutputs(vrfOutputs []VRFBeaconTypesVRFOutput, juelsPerFeeCoin *big.Int, reasonableGasPrice uint64, blockHeight uint64) (*types.Transaction, error) { + return _VRFCoordinator.Contract.ProcessVRFOutputs(&_VRFCoordinator.TransactOpts, vrfOutputs, juelsPerFeeCoin, reasonableGasPrice, blockHeight) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) RedeemRandomness(opts *bind.TransactOpts, subID *big.Int, requestID *big.Int, arg2 []byte) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "redeemRandomness", subID, requestID, arg2) +} + +func (_VRFCoordinator *VRFCoordinatorSession) RedeemRandomness(subID *big.Int, requestID *big.Int, arg2 []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RedeemRandomness(&_VRFCoordinator.TransactOpts, subID, requestID, arg2) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) RedeemRandomness(subID *big.Int, requestID *big.Int, arg2 []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RedeemRandomness(&_VRFCoordinator.TransactOpts, subID, requestID, arg2) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) RegisterMigratableCoordinator(opts *bind.TransactOpts, target common.Address) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "registerMigratableCoordinator", target) +} + +func (_VRFCoordinator *VRFCoordinatorSession) RegisterMigratableCoordinator(target common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RegisterMigratableCoordinator(&_VRFCoordinator.TransactOpts, target) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) RegisterMigratableCoordinator(target common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RegisterMigratableCoordinator(&_VRFCoordinator.TransactOpts, target) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) RemoveConsumer(opts *bind.TransactOpts, subId *big.Int, consumer common.Address) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "removeConsumer", subId, consumer) +} + +func (_VRFCoordinator *VRFCoordinatorSession) RemoveConsumer(subId *big.Int, consumer common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RemoveConsumer(&_VRFCoordinator.TransactOpts, subId, consumer) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) RemoveConsumer(subId *big.Int, consumer common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RemoveConsumer(&_VRFCoordinator.TransactOpts, subId, consumer) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) RequestRandomness(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confDelay *big.Int, arg3 []byte) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "requestRandomness", subID, numWords, confDelay, arg3) +} + +func (_VRFCoordinator *VRFCoordinatorSession) RequestRandomness(subID *big.Int, numWords uint16, confDelay *big.Int, arg3 []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RequestRandomness(&_VRFCoordinator.TransactOpts, subID, numWords, confDelay, arg3) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) RequestRandomness(subID *big.Int, numWords uint16, confDelay *big.Int, arg3 []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RequestRandomness(&_VRFCoordinator.TransactOpts, subID, numWords, confDelay, arg3) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) RequestRandomnessFulfillment(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte, arg5 []byte) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "requestRandomnessFulfillment", subID, numWords, confDelay, callbackGasLimit, arguments, arg5) +} + +func (_VRFCoordinator *VRFCoordinatorSession) RequestRandomnessFulfillment(subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte, arg5 []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RequestRandomnessFulfillment(&_VRFCoordinator.TransactOpts, subID, numWords, confDelay, callbackGasLimit, arguments, arg5) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) RequestRandomnessFulfillment(subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte, arg5 []byte) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RequestRandomnessFulfillment(&_VRFCoordinator.TransactOpts, subID, numWords, confDelay, callbackGasLimit, arguments, arg5) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) RequestSubscriptionOwnerTransfer(opts *bind.TransactOpts, subId *big.Int, newOwner common.Address) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "requestSubscriptionOwnerTransfer", subId, newOwner) +} + +func (_VRFCoordinator *VRFCoordinatorSession) RequestSubscriptionOwnerTransfer(subId *big.Int, newOwner common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RequestSubscriptionOwnerTransfer(&_VRFCoordinator.TransactOpts, subId, newOwner) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) RequestSubscriptionOwnerTransfer(subId *big.Int, newOwner common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.RequestSubscriptionOwnerTransfer(&_VRFCoordinator.TransactOpts, subId, newOwner) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) SetCallbackConfig(opts *bind.TransactOpts, config VRFCoordinatorCallbackConfig) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "setCallbackConfig", config) +} + +func (_VRFCoordinator *VRFCoordinatorSession) SetCallbackConfig(config VRFCoordinatorCallbackConfig) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetCallbackConfig(&_VRFCoordinator.TransactOpts, config) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) SetCallbackConfig(config VRFCoordinatorCallbackConfig) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetCallbackConfig(&_VRFCoordinator.TransactOpts, config) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) SetConfirmationDelays(opts *bind.TransactOpts, confDelays [8]*big.Int) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "setConfirmationDelays", confDelays) +} + +func (_VRFCoordinator *VRFCoordinatorSession) SetConfirmationDelays(confDelays [8]*big.Int) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetConfirmationDelays(&_VRFCoordinator.TransactOpts, confDelays) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) SetConfirmationDelays(confDelays [8]*big.Int) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetConfirmationDelays(&_VRFCoordinator.TransactOpts, confDelays) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) SetCoordinatorConfig(opts *bind.TransactOpts, coordinatorConfig VRFBeaconTypesCoordinatorConfig) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "setCoordinatorConfig", coordinatorConfig) +} + +func (_VRFCoordinator *VRFCoordinatorSession) SetCoordinatorConfig(coordinatorConfig VRFBeaconTypesCoordinatorConfig) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetCoordinatorConfig(&_VRFCoordinator.TransactOpts, coordinatorConfig) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) SetCoordinatorConfig(coordinatorConfig VRFBeaconTypesCoordinatorConfig) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetCoordinatorConfig(&_VRFCoordinator.TransactOpts, coordinatorConfig) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) SetPauseFlag(opts *bind.TransactOpts, pause bool) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "setPauseFlag", pause) +} + +func (_VRFCoordinator *VRFCoordinatorSession) SetPauseFlag(pause bool) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetPauseFlag(&_VRFCoordinator.TransactOpts, pause) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) SetPauseFlag(pause bool) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetPauseFlag(&_VRFCoordinator.TransactOpts, pause) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) SetProducer(opts *bind.TransactOpts, producer common.Address) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "setProducer", producer) +} + +func (_VRFCoordinator *VRFCoordinatorSession) SetProducer(producer common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetProducer(&_VRFCoordinator.TransactOpts, producer) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) SetProducer(producer common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.SetProducer(&_VRFCoordinator.TransactOpts, producer) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) TransferLink(opts *bind.TransactOpts, recipient common.Address, juelsAmount *big.Int) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "transferLink", recipient, juelsAmount) +} + +func (_VRFCoordinator *VRFCoordinatorSession) TransferLink(recipient common.Address, juelsAmount *big.Int) (*types.Transaction, error) { + return _VRFCoordinator.Contract.TransferLink(&_VRFCoordinator.TransactOpts, recipient, juelsAmount) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) TransferLink(recipient common.Address, juelsAmount *big.Int) (*types.Transaction, error) { + return _VRFCoordinator.Contract.TransferLink(&_VRFCoordinator.TransactOpts, recipient, juelsAmount) +} + +func (_VRFCoordinator *VRFCoordinatorTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _VRFCoordinator.contract.Transact(opts, "transferOwnership", to) +} + +func (_VRFCoordinator *VRFCoordinatorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.TransferOwnership(&_VRFCoordinator.TransactOpts, to) +} + +func (_VRFCoordinator *VRFCoordinatorTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _VRFCoordinator.Contract.TransferOwnership(&_VRFCoordinator.TransactOpts, to) +} + +type VRFCoordinatorCallbackConfigSetIterator struct { + Event *VRFCoordinatorCallbackConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorCallbackConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorCallbackConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorCallbackConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorCallbackConfigSetIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorCallbackConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorCallbackConfigSet struct { + NewConfig VRFCoordinatorCallbackConfig + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterCallbackConfigSet(opts *bind.FilterOpts) (*VRFCoordinatorCallbackConfigSetIterator, error) { + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "CallbackConfigSet") + if err != nil { + return nil, err + } + return &VRFCoordinatorCallbackConfigSetIterator{contract: _VRFCoordinator.contract, event: "CallbackConfigSet", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchCallbackConfigSet(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorCallbackConfigSet) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "CallbackConfigSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorCallbackConfigSet) + if err := _VRFCoordinator.contract.UnpackLog(event, "CallbackConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseCallbackConfigSet(log types.Log) (*VRFCoordinatorCallbackConfigSet, error) { + event := new(VRFCoordinatorCallbackConfigSet) + if err := _VRFCoordinator.contract.UnpackLog(event, "CallbackConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorCoordinatorConfigSetIterator struct { + Event *VRFCoordinatorCoordinatorConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorCoordinatorConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorCoordinatorConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorCoordinatorConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorCoordinatorConfigSetIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorCoordinatorConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorCoordinatorConfigSet struct { + CoordinatorConfig VRFBeaconTypesCoordinatorConfig + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterCoordinatorConfigSet(opts *bind.FilterOpts) (*VRFCoordinatorCoordinatorConfigSetIterator, error) { + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "CoordinatorConfigSet") + if err != nil { + return nil, err + } + return &VRFCoordinatorCoordinatorConfigSetIterator{contract: _VRFCoordinator.contract, event: "CoordinatorConfigSet", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchCoordinatorConfigSet(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorCoordinatorConfigSet) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "CoordinatorConfigSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorCoordinatorConfigSet) + if err := _VRFCoordinator.contract.UnpackLog(event, "CoordinatorConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseCoordinatorConfigSet(log types.Log) (*VRFCoordinatorCoordinatorConfigSet, error) { + event := new(VRFCoordinatorCoordinatorConfigSet) + if err := _VRFCoordinator.contract.UnpackLog(event, "CoordinatorConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorCoordinatorDeregisteredIterator struct { + Event *VRFCoordinatorCoordinatorDeregistered + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorCoordinatorDeregisteredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorCoordinatorDeregistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorCoordinatorDeregistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorCoordinatorDeregisteredIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorCoordinatorDeregisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorCoordinatorDeregistered struct { + CoordinatorAddress common.Address + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterCoordinatorDeregistered(opts *bind.FilterOpts) (*VRFCoordinatorCoordinatorDeregisteredIterator, error) { + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "CoordinatorDeregistered") + if err != nil { + return nil, err + } + return &VRFCoordinatorCoordinatorDeregisteredIterator{contract: _VRFCoordinator.contract, event: "CoordinatorDeregistered", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchCoordinatorDeregistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorCoordinatorDeregistered) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "CoordinatorDeregistered") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorCoordinatorDeregistered) + if err := _VRFCoordinator.contract.UnpackLog(event, "CoordinatorDeregistered", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseCoordinatorDeregistered(log types.Log) (*VRFCoordinatorCoordinatorDeregistered, error) { + event := new(VRFCoordinatorCoordinatorDeregistered) + if err := _VRFCoordinator.contract.UnpackLog(event, "CoordinatorDeregistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorCoordinatorRegisteredIterator struct { + Event *VRFCoordinatorCoordinatorRegistered + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorCoordinatorRegisteredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorCoordinatorRegistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorCoordinatorRegistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorCoordinatorRegisteredIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorCoordinatorRegisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorCoordinatorRegistered struct { + CoordinatorAddress common.Address + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterCoordinatorRegistered(opts *bind.FilterOpts) (*VRFCoordinatorCoordinatorRegisteredIterator, error) { + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "CoordinatorRegistered") + if err != nil { + return nil, err + } + return &VRFCoordinatorCoordinatorRegisteredIterator{contract: _VRFCoordinator.contract, event: "CoordinatorRegistered", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchCoordinatorRegistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorCoordinatorRegistered) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "CoordinatorRegistered") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorCoordinatorRegistered) + if err := _VRFCoordinator.contract.UnpackLog(event, "CoordinatorRegistered", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseCoordinatorRegistered(log types.Log) (*VRFCoordinatorCoordinatorRegistered, error) { + event := new(VRFCoordinatorCoordinatorRegistered) + if err := _VRFCoordinator.contract.UnpackLog(event, "CoordinatorRegistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorMigrationCompletedIterator struct { + Event *VRFCoordinatorMigrationCompleted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorMigrationCompletedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorMigrationCompleted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorMigrationCompleted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorMigrationCompletedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorMigrationCompletedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorMigrationCompleted struct { + NewVersion uint8 + NewCoordinator common.Address + SubID *big.Int + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterMigrationCompleted(opts *bind.FilterOpts, newVersion []uint8, subID []*big.Int) (*VRFCoordinatorMigrationCompletedIterator, error) { + + var newVersionRule []interface{} + for _, newVersionItem := range newVersion { + newVersionRule = append(newVersionRule, newVersionItem) + } + + var subIDRule []interface{} + for _, subIDItem := range subID { + subIDRule = append(subIDRule, subIDItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "MigrationCompleted", newVersionRule, subIDRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorMigrationCompletedIterator{contract: _VRFCoordinator.contract, event: "MigrationCompleted", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchMigrationCompleted(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorMigrationCompleted, newVersion []uint8, subID []*big.Int) (event.Subscription, error) { + + var newVersionRule []interface{} + for _, newVersionItem := range newVersion { + newVersionRule = append(newVersionRule, newVersionItem) + } + + var subIDRule []interface{} + for _, subIDItem := range subID { + subIDRule = append(subIDRule, subIDItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "MigrationCompleted", newVersionRule, subIDRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorMigrationCompleted) + if err := _VRFCoordinator.contract.UnpackLog(event, "MigrationCompleted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseMigrationCompleted(log types.Log) (*VRFCoordinatorMigrationCompleted, error) { + event := new(VRFCoordinatorMigrationCompleted) + if err := _VRFCoordinator.contract.UnpackLog(event, "MigrationCompleted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorOutputsServedIterator struct { + Event *VRFCoordinatorOutputsServed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorOutputsServedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorOutputsServed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorOutputsServed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorOutputsServedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorOutputsServedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorOutputsServed struct { + RecentBlockHeight uint64 + JuelsPerFeeCoin *big.Int + ReasonableGasPrice uint64 + OutputsServed []VRFBeaconTypesOutputServed + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterOutputsServed(opts *bind.FilterOpts) (*VRFCoordinatorOutputsServedIterator, error) { + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "OutputsServed") + if err != nil { + return nil, err + } + return &VRFCoordinatorOutputsServedIterator{contract: _VRFCoordinator.contract, event: "OutputsServed", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchOutputsServed(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorOutputsServed) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "OutputsServed") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorOutputsServed) + if err := _VRFCoordinator.contract.UnpackLog(event, "OutputsServed", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseOutputsServed(log types.Log) (*VRFCoordinatorOutputsServed, error) { + event := new(VRFCoordinatorOutputsServed) + if err := _VRFCoordinator.contract.UnpackLog(event, "OutputsServed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorOwnershipTransferRequestedIterator struct { + Event *VRFCoordinatorOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFCoordinatorOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorOwnershipTransferRequestedIterator{contract: _VRFCoordinator.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorOwnershipTransferRequested) + if err := _VRFCoordinator.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseOwnershipTransferRequested(log types.Log) (*VRFCoordinatorOwnershipTransferRequested, error) { + event := new(VRFCoordinatorOwnershipTransferRequested) + if err := _VRFCoordinator.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorOwnershipTransferredIterator struct { + Event *VRFCoordinatorOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFCoordinatorOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorOwnershipTransferredIterator{contract: _VRFCoordinator.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorOwnershipTransferred) + if err := _VRFCoordinator.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseOwnershipTransferred(log types.Log) (*VRFCoordinatorOwnershipTransferred, error) { + event := new(VRFCoordinatorOwnershipTransferred) + if err := _VRFCoordinator.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorPauseFlagChangedIterator struct { + Event *VRFCoordinatorPauseFlagChanged + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorPauseFlagChangedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorPauseFlagChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorPauseFlagChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorPauseFlagChangedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorPauseFlagChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorPauseFlagChanged struct { + Paused bool + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterPauseFlagChanged(opts *bind.FilterOpts) (*VRFCoordinatorPauseFlagChangedIterator, error) { + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "PauseFlagChanged") + if err != nil { + return nil, err + } + return &VRFCoordinatorPauseFlagChangedIterator{contract: _VRFCoordinator.contract, event: "PauseFlagChanged", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchPauseFlagChanged(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorPauseFlagChanged) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "PauseFlagChanged") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorPauseFlagChanged) + if err := _VRFCoordinator.contract.UnpackLog(event, "PauseFlagChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParsePauseFlagChanged(log types.Log) (*VRFCoordinatorPauseFlagChanged, error) { + event := new(VRFCoordinatorPauseFlagChanged) + if err := _VRFCoordinator.contract.UnpackLog(event, "PauseFlagChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorRandomWordsFulfilledIterator struct { + Event *VRFCoordinatorRandomWordsFulfilled + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorRandomWordsFulfilledIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorRandomWordsFulfilled) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorRandomWordsFulfilled) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorRandomWordsFulfilledIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorRandomWordsFulfilledIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorRandomWordsFulfilled struct { + RequestIDs []*big.Int + SuccessfulFulfillment []byte + TruncatedErrorData [][]byte + SubBalances []*big.Int + SubIDs []*big.Int + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterRandomWordsFulfilled(opts *bind.FilterOpts) (*VRFCoordinatorRandomWordsFulfilledIterator, error) { + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "RandomWordsFulfilled") + if err != nil { + return nil, err + } + return &VRFCoordinatorRandomWordsFulfilledIterator{contract: _VRFCoordinator.contract, event: "RandomWordsFulfilled", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchRandomWordsFulfilled(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorRandomWordsFulfilled) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "RandomWordsFulfilled") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorRandomWordsFulfilled) + if err := _VRFCoordinator.contract.UnpackLog(event, "RandomWordsFulfilled", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseRandomWordsFulfilled(log types.Log) (*VRFCoordinatorRandomWordsFulfilled, error) { + event := new(VRFCoordinatorRandomWordsFulfilled) + if err := _VRFCoordinator.contract.UnpackLog(event, "RandomWordsFulfilled", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorRandomnessFulfillmentRequestedIterator struct { + Event *VRFCoordinatorRandomnessFulfillmentRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorRandomnessFulfillmentRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorRandomnessFulfillmentRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorRandomnessFulfillmentRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorRandomnessFulfillmentRequestedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorRandomnessFulfillmentRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorRandomnessFulfillmentRequested struct { + RequestID *big.Int + Requester common.Address + NextBeaconOutputHeight uint64 + ConfDelay *big.Int + SubID *big.Int + NumWords uint16 + GasAllowance uint32 + GasPrice *big.Int + WeiPerUnitLink *big.Int + Arguments []byte + CostJuels *big.Int + NewSubBalance *big.Int + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterRandomnessFulfillmentRequested(opts *bind.FilterOpts, requestID []*big.Int) (*VRFCoordinatorRandomnessFulfillmentRequestedIterator, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "RandomnessFulfillmentRequested", requestIDRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorRandomnessFulfillmentRequestedIterator{contract: _VRFCoordinator.contract, event: "RandomnessFulfillmentRequested", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchRandomnessFulfillmentRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorRandomnessFulfillmentRequested, requestID []*big.Int) (event.Subscription, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "RandomnessFulfillmentRequested", requestIDRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorRandomnessFulfillmentRequested) + if err := _VRFCoordinator.contract.UnpackLog(event, "RandomnessFulfillmentRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseRandomnessFulfillmentRequested(log types.Log) (*VRFCoordinatorRandomnessFulfillmentRequested, error) { + event := new(VRFCoordinatorRandomnessFulfillmentRequested) + if err := _VRFCoordinator.contract.UnpackLog(event, "RandomnessFulfillmentRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorRandomnessRedeemedIterator struct { + Event *VRFCoordinatorRandomnessRedeemed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorRandomnessRedeemedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorRandomnessRedeemed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorRandomnessRedeemed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorRandomnessRedeemedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorRandomnessRedeemedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorRandomnessRedeemed struct { + RequestID *big.Int + Requester common.Address + SubID *big.Int + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterRandomnessRedeemed(opts *bind.FilterOpts, requestID []*big.Int, requester []common.Address) (*VRFCoordinatorRandomnessRedeemedIterator, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + var requesterRule []interface{} + for _, requesterItem := range requester { + requesterRule = append(requesterRule, requesterItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "RandomnessRedeemed", requestIDRule, requesterRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorRandomnessRedeemedIterator{contract: _VRFCoordinator.contract, event: "RandomnessRedeemed", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchRandomnessRedeemed(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorRandomnessRedeemed, requestID []*big.Int, requester []common.Address) (event.Subscription, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + var requesterRule []interface{} + for _, requesterItem := range requester { + requesterRule = append(requesterRule, requesterItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "RandomnessRedeemed", requestIDRule, requesterRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorRandomnessRedeemed) + if err := _VRFCoordinator.contract.UnpackLog(event, "RandomnessRedeemed", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseRandomnessRedeemed(log types.Log) (*VRFCoordinatorRandomnessRedeemed, error) { + event := new(VRFCoordinatorRandomnessRedeemed) + if err := _VRFCoordinator.contract.UnpackLog(event, "RandomnessRedeemed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorRandomnessRequestedIterator struct { + Event *VRFCoordinatorRandomnessRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorRandomnessRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorRandomnessRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorRandomnessRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorRandomnessRequestedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorRandomnessRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorRandomnessRequested struct { + RequestID *big.Int + Requester common.Address + NextBeaconOutputHeight uint64 + ConfDelay *big.Int + SubID *big.Int + NumWords uint16 + CostJuels *big.Int + NewSubBalance *big.Int + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterRandomnessRequested(opts *bind.FilterOpts, requestID []*big.Int) (*VRFCoordinatorRandomnessRequestedIterator, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "RandomnessRequested", requestIDRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorRandomnessRequestedIterator{contract: _VRFCoordinator.contract, event: "RandomnessRequested", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchRandomnessRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorRandomnessRequested, requestID []*big.Int) (event.Subscription, error) { + + var requestIDRule []interface{} + for _, requestIDItem := range requestID { + requestIDRule = append(requestIDRule, requestIDItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "RandomnessRequested", requestIDRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorRandomnessRequested) + if err := _VRFCoordinator.contract.UnpackLog(event, "RandomnessRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseRandomnessRequested(log types.Log) (*VRFCoordinatorRandomnessRequested, error) { + event := new(VRFCoordinatorRandomnessRequested) + if err := _VRFCoordinator.contract.UnpackLog(event, "RandomnessRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorSubscriptionCanceledIterator struct { + Event *VRFCoordinatorSubscriptionCanceled + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorSubscriptionCanceledIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionCanceled) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionCanceled) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorSubscriptionCanceledIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorSubscriptionCanceledIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorSubscriptionCanceled struct { + SubId *big.Int + To common.Address + Amount *big.Int + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterSubscriptionCanceled(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionCanceledIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "SubscriptionCanceled", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorSubscriptionCanceledIterator{contract: _VRFCoordinator.contract, event: "SubscriptionCanceled", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchSubscriptionCanceled(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionCanceled, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "SubscriptionCanceled", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorSubscriptionCanceled) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionCanceled", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseSubscriptionCanceled(log types.Log) (*VRFCoordinatorSubscriptionCanceled, error) { + event := new(VRFCoordinatorSubscriptionCanceled) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionCanceled", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorSubscriptionConsumerAddedIterator struct { + Event *VRFCoordinatorSubscriptionConsumerAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorSubscriptionConsumerAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionConsumerAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionConsumerAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorSubscriptionConsumerAddedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorSubscriptionConsumerAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorSubscriptionConsumerAdded struct { + SubId *big.Int + Consumer common.Address + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterSubscriptionConsumerAdded(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionConsumerAddedIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "SubscriptionConsumerAdded", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorSubscriptionConsumerAddedIterator{contract: _VRFCoordinator.contract, event: "SubscriptionConsumerAdded", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchSubscriptionConsumerAdded(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionConsumerAdded, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "SubscriptionConsumerAdded", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorSubscriptionConsumerAdded) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionConsumerAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseSubscriptionConsumerAdded(log types.Log) (*VRFCoordinatorSubscriptionConsumerAdded, error) { + event := new(VRFCoordinatorSubscriptionConsumerAdded) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionConsumerAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorSubscriptionConsumerRemovedIterator struct { + Event *VRFCoordinatorSubscriptionConsumerRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorSubscriptionConsumerRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionConsumerRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionConsumerRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorSubscriptionConsumerRemovedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorSubscriptionConsumerRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorSubscriptionConsumerRemoved struct { + SubId *big.Int + Consumer common.Address + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterSubscriptionConsumerRemoved(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionConsumerRemovedIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "SubscriptionConsumerRemoved", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorSubscriptionConsumerRemovedIterator{contract: _VRFCoordinator.contract, event: "SubscriptionConsumerRemoved", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchSubscriptionConsumerRemoved(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionConsumerRemoved, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "SubscriptionConsumerRemoved", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorSubscriptionConsumerRemoved) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionConsumerRemoved", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseSubscriptionConsumerRemoved(log types.Log) (*VRFCoordinatorSubscriptionConsumerRemoved, error) { + event := new(VRFCoordinatorSubscriptionConsumerRemoved) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionConsumerRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorSubscriptionCreatedIterator struct { + Event *VRFCoordinatorSubscriptionCreated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorSubscriptionCreatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionCreated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionCreated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorSubscriptionCreatedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorSubscriptionCreatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorSubscriptionCreated struct { + SubId *big.Int + Owner common.Address + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterSubscriptionCreated(opts *bind.FilterOpts, subId []*big.Int, owner []common.Address) (*VRFCoordinatorSubscriptionCreatedIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "SubscriptionCreated", subIdRule, ownerRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorSubscriptionCreatedIterator{contract: _VRFCoordinator.contract, event: "SubscriptionCreated", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchSubscriptionCreated(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionCreated, subId []*big.Int, owner []common.Address) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "SubscriptionCreated", subIdRule, ownerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorSubscriptionCreated) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionCreated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseSubscriptionCreated(log types.Log) (*VRFCoordinatorSubscriptionCreated, error) { + event := new(VRFCoordinatorSubscriptionCreated) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionCreated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorSubscriptionFundedIterator struct { + Event *VRFCoordinatorSubscriptionFunded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorSubscriptionFundedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionFunded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionFunded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorSubscriptionFundedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorSubscriptionFundedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorSubscriptionFunded struct { + SubId *big.Int + OldBalance *big.Int + NewBalance *big.Int + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterSubscriptionFunded(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionFundedIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "SubscriptionFunded", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorSubscriptionFundedIterator{contract: _VRFCoordinator.contract, event: "SubscriptionFunded", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchSubscriptionFunded(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionFunded, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "SubscriptionFunded", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorSubscriptionFunded) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionFunded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseSubscriptionFunded(log types.Log) (*VRFCoordinatorSubscriptionFunded, error) { + event := new(VRFCoordinatorSubscriptionFunded) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionFunded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorSubscriptionOwnerTransferRequestedIterator struct { + Event *VRFCoordinatorSubscriptionOwnerTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorSubscriptionOwnerTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionOwnerTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionOwnerTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorSubscriptionOwnerTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorSubscriptionOwnerTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorSubscriptionOwnerTransferRequested struct { + SubId *big.Int + From common.Address + To common.Address + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterSubscriptionOwnerTransferRequested(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionOwnerTransferRequestedIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "SubscriptionOwnerTransferRequested", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorSubscriptionOwnerTransferRequestedIterator{contract: _VRFCoordinator.contract, event: "SubscriptionOwnerTransferRequested", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchSubscriptionOwnerTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionOwnerTransferRequested, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "SubscriptionOwnerTransferRequested", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorSubscriptionOwnerTransferRequested) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionOwnerTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseSubscriptionOwnerTransferRequested(log types.Log) (*VRFCoordinatorSubscriptionOwnerTransferRequested, error) { + event := new(VRFCoordinatorSubscriptionOwnerTransferRequested) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionOwnerTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type VRFCoordinatorSubscriptionOwnerTransferredIterator struct { + Event *VRFCoordinatorSubscriptionOwnerTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorSubscriptionOwnerTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionOwnerTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorSubscriptionOwnerTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorSubscriptionOwnerTransferredIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorSubscriptionOwnerTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorSubscriptionOwnerTransferred struct { + SubId *big.Int + From common.Address + To common.Address + Raw types.Log +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) FilterSubscriptionOwnerTransferred(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionOwnerTransferredIterator, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.FilterLogs(opts, "SubscriptionOwnerTransferred", subIdRule) + if err != nil { + return nil, err + } + return &VRFCoordinatorSubscriptionOwnerTransferredIterator{contract: _VRFCoordinator.contract, event: "SubscriptionOwnerTransferred", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) WatchSubscriptionOwnerTransferred(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionOwnerTransferred, subId []*big.Int) (event.Subscription, error) { + + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) + } + + logs, sub, err := _VRFCoordinator.contract.WatchLogs(opts, "SubscriptionOwnerTransferred", subIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorSubscriptionOwnerTransferred) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionOwnerTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinator *VRFCoordinatorFilterer) ParseSubscriptionOwnerTransferred(log types.Log) (*VRFCoordinatorSubscriptionOwnerTransferred, error) { + event := new(VRFCoordinatorSubscriptionOwnerTransferred) + if err := _VRFCoordinator.contract.UnpackLog(event, "SubscriptionOwnerTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type GetSubscription struct { + Balance *big.Int + PendingFulfillments uint64 + Owner common.Address + Consumers []common.Address +} +type SCallbackConfig struct { + MaxCallbackGasLimit uint32 + MaxCallbackArgumentsLength uint32 +} +type SCoordinatorConfig struct { + UseReasonableGasPrice bool + ReentrancyLock bool + Paused bool + PremiumPercentage uint8 + UnusedGasPenaltyPercent uint8 + StalenessSeconds uint32 + RedeemableRequestGasOverhead uint32 + CallbackRequestGasOverhead uint32 + ReasonableGasPriceStalenessBlocks uint32 + FallbackWeiPerUnitLink *big.Int +} +type SPendingRequests struct { + SlotNumber uint32 + ConfirmationDelay *big.Int + NumWords uint16 + Requester common.Address +} + +func (_VRFCoordinator *VRFCoordinator) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _VRFCoordinator.abi.Events["CallbackConfigSet"].ID: + return _VRFCoordinator.ParseCallbackConfigSet(log) + case _VRFCoordinator.abi.Events["CoordinatorConfigSet"].ID: + return _VRFCoordinator.ParseCoordinatorConfigSet(log) + case _VRFCoordinator.abi.Events["CoordinatorDeregistered"].ID: + return _VRFCoordinator.ParseCoordinatorDeregistered(log) + case _VRFCoordinator.abi.Events["CoordinatorRegistered"].ID: + return _VRFCoordinator.ParseCoordinatorRegistered(log) + case _VRFCoordinator.abi.Events["MigrationCompleted"].ID: + return _VRFCoordinator.ParseMigrationCompleted(log) + case _VRFCoordinator.abi.Events["OutputsServed"].ID: + return _VRFCoordinator.ParseOutputsServed(log) + case _VRFCoordinator.abi.Events["OwnershipTransferRequested"].ID: + return _VRFCoordinator.ParseOwnershipTransferRequested(log) + case _VRFCoordinator.abi.Events["OwnershipTransferred"].ID: + return _VRFCoordinator.ParseOwnershipTransferred(log) + case _VRFCoordinator.abi.Events["PauseFlagChanged"].ID: + return _VRFCoordinator.ParsePauseFlagChanged(log) + case _VRFCoordinator.abi.Events["RandomWordsFulfilled"].ID: + return _VRFCoordinator.ParseRandomWordsFulfilled(log) + case _VRFCoordinator.abi.Events["RandomnessFulfillmentRequested"].ID: + return _VRFCoordinator.ParseRandomnessFulfillmentRequested(log) + case _VRFCoordinator.abi.Events["RandomnessRedeemed"].ID: + return _VRFCoordinator.ParseRandomnessRedeemed(log) + case _VRFCoordinator.abi.Events["RandomnessRequested"].ID: + return _VRFCoordinator.ParseRandomnessRequested(log) + case _VRFCoordinator.abi.Events["SubscriptionCanceled"].ID: + return _VRFCoordinator.ParseSubscriptionCanceled(log) + case _VRFCoordinator.abi.Events["SubscriptionConsumerAdded"].ID: + return _VRFCoordinator.ParseSubscriptionConsumerAdded(log) + case _VRFCoordinator.abi.Events["SubscriptionConsumerRemoved"].ID: + return _VRFCoordinator.ParseSubscriptionConsumerRemoved(log) + case _VRFCoordinator.abi.Events["SubscriptionCreated"].ID: + return _VRFCoordinator.ParseSubscriptionCreated(log) + case _VRFCoordinator.abi.Events["SubscriptionFunded"].ID: + return _VRFCoordinator.ParseSubscriptionFunded(log) + case _VRFCoordinator.abi.Events["SubscriptionOwnerTransferRequested"].ID: + return _VRFCoordinator.ParseSubscriptionOwnerTransferRequested(log) + case _VRFCoordinator.abi.Events["SubscriptionOwnerTransferred"].ID: + return _VRFCoordinator.ParseSubscriptionOwnerTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (VRFCoordinatorCallbackConfigSet) Topic() common.Hash { + return common.HexToHash("0x0cc54509a45ab33cd67614d4a2892c083ecf8fb43b9d29f6ea8130b9023e51df") +} + +func (VRFCoordinatorCoordinatorConfigSet) Topic() common.Hash { + return common.HexToHash("0x0028d3a46e95e67def989d41c66eb331add9809460b95b5fb4eb006157728fc5") +} + +func (VRFCoordinatorCoordinatorDeregistered) Topic() common.Hash { + return common.HexToHash("0xf80a1a97fd42251f3c33cda98635e7399253033a6774fe37cd3f650b5282af37") +} + +func (VRFCoordinatorCoordinatorRegistered) Topic() common.Hash { + return common.HexToHash("0xb7cabbfc11e66731fc77de0444614282023bcbd41d16781c753a431d0af01625") +} + +func (VRFCoordinatorMigrationCompleted) Topic() common.Hash { + return common.HexToHash("0xbd89b747474d3fc04664dfbd1d56ae7ffbe46ee097cdb9979c13916bb76269ce") +} + +func (VRFCoordinatorOutputsServed) Topic() common.Hash { + return common.HexToHash("0xf10ea936d00579b4c52035ee33bf46929646b3aa87554c565d8fb2c7aa549c44") +} + +func (VRFCoordinatorOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (VRFCoordinatorOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (VRFCoordinatorPauseFlagChanged) Topic() common.Hash { + return common.HexToHash("0x49ba7c1de2d8853088b6270e43df2118516b217f38b917dd2b80dea360860fbe") +} + +func (VRFCoordinatorRandomWordsFulfilled) Topic() common.Hash { + return common.HexToHash("0x8f79f730779e875ce76c428039cc2052b5b5918c2a55c598fab251c1198aec54") +} + +func (VRFCoordinatorRandomnessFulfillmentRequested) Topic() common.Hash { + return common.HexToHash("0x01872fb9c7d6d68af06a17347935e04412da302a377224c205e672c26e18c37f") +} + +func (VRFCoordinatorRandomnessRedeemed) Topic() common.Hash { + return common.HexToHash("0x16f3f633197fafab10a5df69e6f3f2f7f20092f08d8d47de0a91c0f4b96a1a25") +} + +func (VRFCoordinatorRandomnessRequested) Topic() common.Hash { + return common.HexToHash("0xb7933fba96b6b452eb44f99fdc08052a45dff82363d59abaff0456931c3d2459") +} + +func (VRFCoordinatorSubscriptionCanceled) Topic() common.Hash { + return common.HexToHash("0x3784f77e8e883de95b5d47cd713ced01229fa74d118c0a462224bcb0516d43f1") +} + +func (VRFCoordinatorSubscriptionConsumerAdded) Topic() common.Hash { + return common.HexToHash("0x1e980d04aa7648e205713e5e8ea3808672ac163d10936d36f91b2c88ac1575e1") +} + +func (VRFCoordinatorSubscriptionConsumerRemoved) Topic() common.Hash { + return common.HexToHash("0x32158c6058347c1601b2d12bc696ac6901d8a9a9aa3ba10c27ab0a983e8425a7") +} + +func (VRFCoordinatorSubscriptionCreated) Topic() common.Hash { + return common.HexToHash("0x1d3015d7ba850fa198dc7b1a3f5d42779313a681035f77c8c03764c61005518d") +} + +func (VRFCoordinatorSubscriptionFunded) Topic() common.Hash { + return common.HexToHash("0x1ced9348ff549fceab2ac57cd3a9de38edaaab274b725ee82c23e8fc8c4eec7a") +} + +func (VRFCoordinatorSubscriptionOwnerTransferRequested) Topic() common.Hash { + return common.HexToHash("0x21a4dad170a6bf476c31bbcf4a16628295b0e450672eec25d7c93308e05344a1") +} + +func (VRFCoordinatorSubscriptionOwnerTransferred) Topic() common.Hash { + return common.HexToHash("0xd4114ab6e9af9f597c52041f32d62dc57c5c4e4c0d4427006069635e216c9386") +} + +func (_VRFCoordinator *VRFCoordinator) Address() common.Address { + return _VRFCoordinator.address +} + +type VRFCoordinatorInterface interface { + MAXCONSUMERS(opts *bind.CallOpts) (uint16, error) + + MAXNUMWORDS(opts *bind.CallOpts) (*big.Int, error) + + NUMCONFDELAYS(opts *bind.CallOpts) (uint8, error) + + GetCallbackMemo(opts *bind.CallOpts, requestId *big.Int) ([32]byte, error) + + GetConfirmationDelays(opts *bind.CallOpts) ([8]*big.Int, error) + + GetFee(opts *bind.CallOpts, arg0 *big.Int, arg1 []byte) (*big.Int, error) + + GetFulfillmentFee(opts *bind.CallOpts, arg0 *big.Int, callbackGasLimit uint32, arguments []byte, arg3 []byte) (*big.Int, error) + + GetSubscription(opts *bind.CallOpts, subId *big.Int) (GetSubscription, + + error) + + GetSubscriptionLinkBalance(opts *bind.CallOpts) (*big.Int, error) + + IBeaconPeriodBlocks(opts *bind.CallOpts) (*big.Int, error) + + ILink(opts *bind.CallOpts) (common.Address, error) + + MigrationVersion(opts *bind.CallOpts) (uint8, error) + + OnMigration(opts *bind.CallOpts, arg0 []byte) error + + Owner(opts *bind.CallOpts) (common.Address, error) + + SCallbackConfig(opts *bind.CallOpts) (SCallbackConfig, + + error) + + SCoordinatorConfig(opts *bind.CallOpts) (SCoordinatorConfig, + + error) + + SPendingRequests(opts *bind.CallOpts, arg0 *big.Int) (SPendingRequests, + + error) + + SProducer(opts *bind.CallOpts) (common.Address, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + AcceptSubscriptionOwnerTransfer(opts *bind.TransactOpts, subId *big.Int) (*types.Transaction, error) + + AddConsumer(opts *bind.TransactOpts, subId *big.Int, consumer common.Address) (*types.Transaction, error) + + BatchTransferLink(opts *bind.TransactOpts, recipients []common.Address, paymentsInJuels []*big.Int) (*types.Transaction, error) + + CancelSubscription(opts *bind.TransactOpts, subId *big.Int, to common.Address) (*types.Transaction, error) + + CreateSubscription(opts *bind.TransactOpts) (*types.Transaction, error) + + DeregisterMigratableCoordinator(opts *bind.TransactOpts, target common.Address) (*types.Transaction, error) + + Migrate(opts *bind.TransactOpts, newCoordinator common.Address, encodedRequest []byte) (*types.Transaction, error) + + OnTokenTransfer(opts *bind.TransactOpts, arg0 common.Address, amount *big.Int, data []byte) (*types.Transaction, error) + + ProcessVRFOutputs(opts *bind.TransactOpts, vrfOutputs []VRFBeaconTypesVRFOutput, juelsPerFeeCoin *big.Int, reasonableGasPrice uint64, blockHeight uint64) (*types.Transaction, error) + + RedeemRandomness(opts *bind.TransactOpts, subID *big.Int, requestID *big.Int, arg2 []byte) (*types.Transaction, error) + + RegisterMigratableCoordinator(opts *bind.TransactOpts, target common.Address) (*types.Transaction, error) + + RemoveConsumer(opts *bind.TransactOpts, subId *big.Int, consumer common.Address) (*types.Transaction, error) + + RequestRandomness(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confDelay *big.Int, arg3 []byte) (*types.Transaction, error) + + RequestRandomnessFulfillment(opts *bind.TransactOpts, subID *big.Int, numWords uint16, confDelay *big.Int, callbackGasLimit uint32, arguments []byte, arg5 []byte) (*types.Transaction, error) + + RequestSubscriptionOwnerTransfer(opts *bind.TransactOpts, subId *big.Int, newOwner common.Address) (*types.Transaction, error) + + SetCallbackConfig(opts *bind.TransactOpts, config VRFCoordinatorCallbackConfig) (*types.Transaction, error) + + SetConfirmationDelays(opts *bind.TransactOpts, confDelays [8]*big.Int) (*types.Transaction, error) + + SetCoordinatorConfig(opts *bind.TransactOpts, coordinatorConfig VRFBeaconTypesCoordinatorConfig) (*types.Transaction, error) + + SetPauseFlag(opts *bind.TransactOpts, pause bool) (*types.Transaction, error) + + SetProducer(opts *bind.TransactOpts, producer common.Address) (*types.Transaction, error) + + TransferLink(opts *bind.TransactOpts, recipient common.Address, juelsAmount *big.Int) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterCallbackConfigSet(opts *bind.FilterOpts) (*VRFCoordinatorCallbackConfigSetIterator, error) + + WatchCallbackConfigSet(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorCallbackConfigSet) (event.Subscription, error) + + ParseCallbackConfigSet(log types.Log) (*VRFCoordinatorCallbackConfigSet, error) + + FilterCoordinatorConfigSet(opts *bind.FilterOpts) (*VRFCoordinatorCoordinatorConfigSetIterator, error) + + WatchCoordinatorConfigSet(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorCoordinatorConfigSet) (event.Subscription, error) + + ParseCoordinatorConfigSet(log types.Log) (*VRFCoordinatorCoordinatorConfigSet, error) + + FilterCoordinatorDeregistered(opts *bind.FilterOpts) (*VRFCoordinatorCoordinatorDeregisteredIterator, error) + + WatchCoordinatorDeregistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorCoordinatorDeregistered) (event.Subscription, error) + + ParseCoordinatorDeregistered(log types.Log) (*VRFCoordinatorCoordinatorDeregistered, error) + + FilterCoordinatorRegistered(opts *bind.FilterOpts) (*VRFCoordinatorCoordinatorRegisteredIterator, error) + + WatchCoordinatorRegistered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorCoordinatorRegistered) (event.Subscription, error) + + ParseCoordinatorRegistered(log types.Log) (*VRFCoordinatorCoordinatorRegistered, error) + + FilterMigrationCompleted(opts *bind.FilterOpts, newVersion []uint8, subID []*big.Int) (*VRFCoordinatorMigrationCompletedIterator, error) + + WatchMigrationCompleted(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorMigrationCompleted, newVersion []uint8, subID []*big.Int) (event.Subscription, error) + + ParseMigrationCompleted(log types.Log) (*VRFCoordinatorMigrationCompleted, error) + + FilterOutputsServed(opts *bind.FilterOpts) (*VRFCoordinatorOutputsServedIterator, error) + + WatchOutputsServed(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorOutputsServed) (event.Subscription, error) + + ParseOutputsServed(log types.Log) (*VRFCoordinatorOutputsServed, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFCoordinatorOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*VRFCoordinatorOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*VRFCoordinatorOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*VRFCoordinatorOwnershipTransferred, error) + + FilterPauseFlagChanged(opts *bind.FilterOpts) (*VRFCoordinatorPauseFlagChangedIterator, error) + + WatchPauseFlagChanged(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorPauseFlagChanged) (event.Subscription, error) + + ParsePauseFlagChanged(log types.Log) (*VRFCoordinatorPauseFlagChanged, error) + + FilterRandomWordsFulfilled(opts *bind.FilterOpts) (*VRFCoordinatorRandomWordsFulfilledIterator, error) + + WatchRandomWordsFulfilled(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorRandomWordsFulfilled) (event.Subscription, error) + + ParseRandomWordsFulfilled(log types.Log) (*VRFCoordinatorRandomWordsFulfilled, error) + + FilterRandomnessFulfillmentRequested(opts *bind.FilterOpts, requestID []*big.Int) (*VRFCoordinatorRandomnessFulfillmentRequestedIterator, error) + + WatchRandomnessFulfillmentRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorRandomnessFulfillmentRequested, requestID []*big.Int) (event.Subscription, error) + + ParseRandomnessFulfillmentRequested(log types.Log) (*VRFCoordinatorRandomnessFulfillmentRequested, error) + + FilterRandomnessRedeemed(opts *bind.FilterOpts, requestID []*big.Int, requester []common.Address) (*VRFCoordinatorRandomnessRedeemedIterator, error) + + WatchRandomnessRedeemed(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorRandomnessRedeemed, requestID []*big.Int, requester []common.Address) (event.Subscription, error) + + ParseRandomnessRedeemed(log types.Log) (*VRFCoordinatorRandomnessRedeemed, error) + + FilterRandomnessRequested(opts *bind.FilterOpts, requestID []*big.Int) (*VRFCoordinatorRandomnessRequestedIterator, error) + + WatchRandomnessRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorRandomnessRequested, requestID []*big.Int) (event.Subscription, error) + + ParseRandomnessRequested(log types.Log) (*VRFCoordinatorRandomnessRequested, error) + + FilterSubscriptionCanceled(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionCanceledIterator, error) + + WatchSubscriptionCanceled(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionCanceled, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionCanceled(log types.Log) (*VRFCoordinatorSubscriptionCanceled, error) + + FilterSubscriptionConsumerAdded(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionConsumerAddedIterator, error) + + WatchSubscriptionConsumerAdded(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionConsumerAdded, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionConsumerAdded(log types.Log) (*VRFCoordinatorSubscriptionConsumerAdded, error) + + FilterSubscriptionConsumerRemoved(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionConsumerRemovedIterator, error) + + WatchSubscriptionConsumerRemoved(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionConsumerRemoved, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionConsumerRemoved(log types.Log) (*VRFCoordinatorSubscriptionConsumerRemoved, error) + + FilterSubscriptionCreated(opts *bind.FilterOpts, subId []*big.Int, owner []common.Address) (*VRFCoordinatorSubscriptionCreatedIterator, error) + + WatchSubscriptionCreated(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionCreated, subId []*big.Int, owner []common.Address) (event.Subscription, error) + + ParseSubscriptionCreated(log types.Log) (*VRFCoordinatorSubscriptionCreated, error) + + FilterSubscriptionFunded(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionFundedIterator, error) + + WatchSubscriptionFunded(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionFunded, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionFunded(log types.Log) (*VRFCoordinatorSubscriptionFunded, error) + + FilterSubscriptionOwnerTransferRequested(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionOwnerTransferRequestedIterator, error) + + WatchSubscriptionOwnerTransferRequested(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionOwnerTransferRequested, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionOwnerTransferRequested(log types.Log) (*VRFCoordinatorSubscriptionOwnerTransferRequested, error) + + FilterSubscriptionOwnerTransferred(opts *bind.FilterOpts, subId []*big.Int) (*VRFCoordinatorSubscriptionOwnerTransferredIterator, error) + + WatchSubscriptionOwnerTransferred(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorSubscriptionOwnerTransferred, subId []*big.Int) (event.Subscription, error) + + ParseSubscriptionOwnerTransferred(log types.Log) (*VRFCoordinatorSubscriptionOwnerTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ocr2vrf/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ocr2vrf/generation/generated-wrapper-dependency-versions-do-not-edit.txt new file mode 100644 index 00000000000..ce0b1a09702 --- /dev/null +++ b/core/gethwrappers/ocr2vrf/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -0,0 +1,7 @@ +GETH_VERSION: 1.12.0 +dkg: ../../../contracts/solc/v0.8.19/DKG.abi ../../../contracts/solc/v0.8.19/DKG.bin 02549733c46e50ba393c2521e39d4ec55b6a5d9a66baf4406b1a515b20470425 +load_test_beacon_consumer: ../../../contracts/solc/v0.8.19/LoadTestBeaconVRFConsumer.abi ../../../contracts/solc/v0.8.19/LoadTestBeaconVRFConsumer.bin 7306576bc1db6c0a4f0a8a83dd4c08e3078afa73b72858f7d1eaa410d1128fd2 +vrf_beacon: ../../../contracts/solc/v0.8.19/VRFBeacon.abi ../../../contracts/solc/v0.8.19/VRFBeacon.bin 63107992adf02024afccbe77fdf973777548dcd4d9af1484c8449aca6de30f4c +vrf_beacon_consumer: ../../../contracts/solc/v0.8.19/BeaconVRFConsumer.abi ../../../contracts/solc/v0.8.19/BeaconVRFConsumer.bin 520f1c24e4d926a4eb6c9504506b55b79a35ae8cc65ee02d28309a7d5b735a53 +vrf_beacon_coordinator: ../../../contracts/solc/v0.8.15/VRFBeaconCoordinator.abi ../../../contracts/solc/v0.8.15/VRFBeaconCoordinator.bin 08da747a3488fcd318ddc0db75fd0df7c07a100b2e19061f0efcb12a7180ecde +vrf_coordinator: ../../../contracts/solc/v0.8.19/VRFCoordinator.abi ../../../contracts/solc/v0.8.19/VRFCoordinator.bin 295bec795ab8c1ef08b6b27a67bab7f06233660e8a2f389211e470cc2b58c5ea diff --git a/core/gethwrappers/ocr2vrf/go_generate.go b/core/gethwrappers/ocr2vrf/go_generate.go new file mode 100644 index 00000000000..475bf7e8f67 --- /dev/null +++ b/core/gethwrappers/ocr2vrf/go_generate.go @@ -0,0 +1,10 @@ +// Package gethwrappers provides tools for wrapping solidity contracts with +// golang packages, using abigen. +package gethwrappers + +// OCR2VRF - remove the _disabled tag to run these locally. +//go:generate_disabled go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/DKG.abi ../../../contracts/solc/v0.8.19/DKG.bin DKG dkg +//go:generate_disabled go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/VRFCoordinator.abi ../../../contracts/solc/v0.8.19/VRFCoordinator.bin VRFCoordinator vrf_coordinator +//go:generate_disabled go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/VRFBeacon.abi ../../../contracts/solc/v0.8.19/VRFBeacon.bin VRFBeacon vrf_beacon +//go:generate_disabled go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/BeaconVRFConsumer.abi ../../../contracts/solc/v0.8.19/BeaconVRFConsumer.bin BeaconVRFConsumer vrf_beacon_consumer +//go:generate_disabled go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/LoadTestBeaconVRFConsumer.abi ../../../contracts/solc/v0.8.19/LoadTestBeaconVRFConsumer.bin LoadTestBeaconVRFConsumer load_test_beacon_consumer diff --git a/core/internal/mocks/go_generate.go b/core/internal/mocks/go_generate.go index 8402f71158d..f3f5f0ae2ca 100644 --- a/core/internal/mocks/go_generate.go +++ b/core/internal/mocks/go_generate.go @@ -4,5 +4,5 @@ package mocks //go:generate mockery --quiet --srcpkg github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flags_wrapper --name FlagsInterface --output . --case=underscore --structname Flags --filename flags.go //go:generate mockery --quiet --srcpkg github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface --name AggregatorV3InterfaceInterface --output ../../services/vrf/mocks/ --case=underscore --structname AggregatorV3Interface --filename aggregator_v3_interface.go //go:generate mockery --quiet --srcpkg github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2 --name VRFCoordinatorV2Interface --output ../../services/vrf/mocks/ --case=underscore --structname VRFCoordinatorV2Interface --filename vrf_coordinator_v2.go -//go:generate mockery --quiet --srcpkg github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon --name VRFBeaconInterface --output ../../services/ocr2/plugins/ocr2vrf/coordinator/mocks --case=underscore --structname VRFBeaconInterface --filename vrf_beacon.go -//go:generate mockery --quiet --srcpkg github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator --name VRFCoordinatorInterface --output ../../services/ocr2/plugins/ocr2vrf/coordinator/mocks --case=underscore --structname VRFCoordinatorInterface --filename vrf_coordinator.go +//go:generate mockery --quiet --srcpkg github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon --name VRFBeaconInterface --output ../../services/ocr2/plugins/ocr2vrf/coordinator/mocks --case=underscore --structname VRFBeaconInterface --filename vrf_beacon.go +//go:generate mockery --quiet --srcpkg github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator --name VRFCoordinatorInterface --output ../../services/ocr2/plugins/ocr2vrf/coordinator/mocks --case=underscore --structname VRFCoordinatorInterface --filename vrf_coordinator.go diff --git a/core/scripts/ocr2vrf/util.go b/core/scripts/ocr2vrf/util.go index a11c799d9a3..e57f349f1fd 100644 --- a/core/scripts/ocr2vrf/util.go +++ b/core/scripts/ocr2vrf/util.go @@ -27,15 +27,15 @@ import ( "github.com/smartcontractkit/chainlink-vrf/ocr2vrf" ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types" - dkgContract "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/dkg" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/load_test_beacon_consumer" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon_consumer" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" + dkgContract "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/dkg" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/load_test_beacon_consumer" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon_consumer" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" ) diff --git a/core/scripts/ocr2vrf/verify.go b/core/scripts/ocr2vrf/verify.go index 36ecda83b5a..7d7fb94496a 100644 --- a/core/scripts/ocr2vrf/verify.go +++ b/core/scripts/ocr2vrf/verify.go @@ -16,10 +16,10 @@ import ( "github.com/smartcontractkit/chainlink-vrf/altbn_128" ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types" - dkgContract "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/dkg" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + dkgContract "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/dkg" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" ) func getDKGLatestConfigDetails(e helpers.Environment, dkgAddress string) dkgContract.LatestConfigDetails { diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go index 4adede8d121..e7688556124 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator.go @@ -28,13 +28,13 @@ import ( "github.com/smartcontractkit/chainlink-vrf/dkg" ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" - vrf_wrapper "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" - dkg_wrapper "github.com/smartcontractkit/chainlink-vrf/gethwrappers/dkg" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + dkg_wrapper "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/dkg" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" + vrf_wrapper "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" ocr2vrfconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2vrf/config" diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go index 1e21227a11e..beee01eaf7a 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/coordinator_test.go @@ -29,12 +29,12 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/mathutil" - dkg_wrapper "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/dkg" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" lp_mocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" + dkg_wrapper "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/dkg" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_beacon.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_beacon.go index 278fe573439..1aeb0ea85c4 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_beacon.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_beacon.go @@ -16,7 +16,7 @@ import ( types "github.com/ethereum/go-ethereum/core/types" - vrf_beacon "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" + vrf_beacon "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" ) // VRFBeaconInterface is an autogenerated mock type for the VRFBeaconInterface type diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_coordinator.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_coordinator.go index 7dddf15a322..268dff05237 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_coordinator.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks/vrf_coordinator.go @@ -16,7 +16,7 @@ import ( types "github.com/ethereum/go-ethereum/core/types" - vrf_coordinator "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" + vrf_coordinator "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" ) // VRFCoordinatorInterface is an autogenerated mock type for the VRFCoordinatorInterface type diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/router.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/router.go index dd7fd5e1ec2..77384a085ab 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/router.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/router.go @@ -8,10 +8,10 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/pkg/errors" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" "github.com/smartcontractkit/chainlink/v2/core/logger" ) diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/router_test.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/router_test.go index c65dcb15a8f..7135fa862e3 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/router_test.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/router_test.go @@ -9,8 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2vrf/coordinator/mocks" ) diff --git a/core/services/ocr2/plugins/ocr2vrf/coordinator/topics.go b/core/services/ocr2/plugins/ocr2vrf/coordinator/topics.go index f8fae150c06..370f0c5fd00 100644 --- a/core/services/ocr2/plugins/ocr2vrf/coordinator/topics.go +++ b/core/services/ocr2/plugins/ocr2vrf/coordinator/topics.go @@ -3,8 +3,8 @@ package coordinator import ( "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" ) type topics struct { diff --git a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go index ac2695dc632..2e1e15fd058 100644 --- a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go +++ b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go @@ -32,11 +32,6 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" - dkg_wrapper "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/dkg" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/load_test_beacon_consumer" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon_consumer" - vrf_wrapper "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -44,6 +39,11 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_v3_aggregator_contract" + dkg_wrapper "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/dkg" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/load_test_beacon_consumer" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon_consumer" + vrf_wrapper "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" diff --git a/go.mod b/go.mod index 0a09e3d9693..6e081467bc0 100644 --- a/go.mod +++ b/go.mod @@ -78,7 +78,7 @@ require ( github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba58 github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 - github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 + github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 diff --git a/go.sum b/go.sum index 68cd0abbd7f..50cb9f3b44f 100644 --- a/go.sum +++ b/go.sum @@ -1192,8 +1192,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba5 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba58/go.mod h1:oV5gIuSKrPEcjQ6uB6smBsm5kXHxyydVLNyAs4V9CoQ= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 h1:y6ks0HsSOhPUueOmTcoxDQ50RCS1XINlRDTemZyHjFw= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595/go.mod h1:vV6WfnVIbK5Q1JsIru4YcTG0T1uRpLJm6t2BgCnCSsg= -github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 h1:LQmRsrzzaYYN3wEU1l5tWiccznhvbyGnu2N+wHSXZAo= -github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= +github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= +github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= diff --git a/integration-tests/contracts/contract_vrf_models.go b/integration-tests/contracts/contract_vrf_models.go index aaccbad0602..f54d1a25936 100644 --- a/integration-tests/contracts/contract_vrf_models.go +++ b/integration-tests/contracts/contract_vrf_models.go @@ -8,8 +8,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/dkg" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" @@ -20,6 +18,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_upgraded_version" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2_wrapper_load_test_consumer" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper_load_test_consumer" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/dkg" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" ) type VRF interface { diff --git a/integration-tests/contracts/ethereum_ocr2vrf_contracts.go b/integration-tests/contracts/ethereum_ocr2vrf_contracts.go index 260af44019f..473b308dc42 100644 --- a/integration-tests/contracts/ethereum_ocr2vrf_contracts.go +++ b/integration-tests/contracts/ethereum_ocr2vrf_contracts.go @@ -13,12 +13,12 @@ import ( "github.com/rs/zerolog/log" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/dkg" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_beacon_consumer" - "github.com/smartcontractkit/chainlink-vrf/archive/gethwrappers/vrf_coordinator" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_coordinator_interface" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/dkg" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_beacon_consumer" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ocr2vrf/generated/vrf_coordinator" ) // EthereumDKG represents DKG contract diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 24a5d1ee7a6..69c09244ef8 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -27,7 +27,7 @@ require ( github.com/smartcontractkit/chainlink-automation v1.0.3 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 github.com/smartcontractkit/chainlink-testing-framework v1.28.4 - github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 + github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c github.com/smartcontractkit/seth v0.1.6 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 8c66ce7ca8c..e2be6f36438 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1531,8 +1531,8 @@ github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.202403 github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595/go.mod h1:vV6WfnVIbK5Q1JsIru4YcTG0T1uRpLJm6t2BgCnCSsg= github.com/smartcontractkit/chainlink-testing-framework v1.28.4 h1:/OOPH76VFQlG5HEXrXgBVDv1fjuasQzMV1EyeaaXWzM= github.com/smartcontractkit/chainlink-testing-framework v1.28.4/go.mod h1:jN+HgXbriq6fKRlIqLw9F3I81aYImV6kBJkIfz0mdIA= -github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 h1:LQmRsrzzaYYN3wEU1l5tWiccznhvbyGnu2N+wHSXZAo= -github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= +github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= +github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 13a8e2f4f34..128c611c04d 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -372,7 +372,7 @@ require ( github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba58 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 // indirect github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240227164431-18a7065e23ea // indirect - github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 // indirect + github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/wsrpc v0.8.1 // indirect github.com/soheilhy/cmux v0.1.5 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 5720d19de02..291f221f4b8 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1516,8 +1516,8 @@ github.com/smartcontractkit/chainlink-testing-framework v1.28.4 h1:/OOPH76VFQlG5 github.com/smartcontractkit/chainlink-testing-framework v1.28.4/go.mod h1:jN+HgXbriq6fKRlIqLw9F3I81aYImV6kBJkIfz0mdIA= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240227164431-18a7065e23ea h1:ZdLmNAfKRjH8AYUvjiiDGUgiWQfq/7iNpxyTkvjx/ko= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240227164431-18a7065e23ea/go.mod h1:gCKC9w6XpNk6jm+XIk2psrkkfxhi421N9NSiFceXW88= -github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 h1:LQmRsrzzaYYN3wEU1l5tWiccznhvbyGnu2N+wHSXZAo= -github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= +github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= +github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= From a293dfe7975b035a71eff7a6197e3ce5a25f1887 Mon Sep 17 00:00:00 2001 From: Lei Date: Wed, 24 Apr 2024 15:39:00 -0700 Subject: [PATCH 08/34] add getters (#12903) * support decimals * address comments * add getters --- .changeset/tasty-lions-rhyme.md | 5 ++ contracts/.changeset/kind-snakes-invent.md | 5 ++ .../v2_3/IAutomationRegistryMaster2_3.sol | 16 +++- .../dev/test/AutomationRegistry2_3.t.sol | 17 ++++ .../dev/v2_3/AutomationRegistryBase2_3.sol | 7 +- .../dev/v2_3/AutomationRegistryLogicC2_3.sol | 31 ++++++++ ..._automation_registry_master_wrapper_2_3.go | 79 ++++++++++++++++++- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 8 files changed, 157 insertions(+), 5 deletions(-) create mode 100644 .changeset/tasty-lions-rhyme.md create mode 100644 contracts/.changeset/kind-snakes-invent.md diff --git a/.changeset/tasty-lions-rhyme.md b/.changeset/tasty-lions-rhyme.md new file mode 100644 index 00000000000..b80f1337bce --- /dev/null +++ b/.changeset/tasty-lions-rhyme.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +add getters #internal diff --git a/contracts/.changeset/kind-snakes-invent.md b/contracts/.changeset/kind-snakes-invent.md new file mode 100644 index 00000000000..abd00ce9c85 --- /dev/null +++ b/contracts/.changeset/kind-snakes-invent.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +add getters #internal diff --git a/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol b/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol index 90fdd82bfe7..c0952963366 100644 --- a/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol +++ b/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol @@ -1,4 +1,4 @@ -// abi-checksum: 0x8860e73056784b47ec03fe67533e66ebf1a6d8e6e708c8046a71ecbe3b9334d9 +// abi-checksum: 0x2cc33080c864676d572ad7ae658ea4a4621b3fd4c4664d84f9945b2324348434 // SPDX-License-Identifier: MIT // !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.6.6. SEE SOURCE BELOW. !! pragma solidity ^0.8.4; @@ -229,6 +229,12 @@ interface IAutomationRegistryMaster2_3 { function getAllowedReadOnlyAddress() external view returns (address); function getAutomationForwarderLogic() external view returns (address); function getBalance(uint256 id) external view returns (uint96 balance); + function getBillingConfig( + address billingToken + ) external view returns (AutomationRegistryBase2_3.BillingConfig memory); + function getBillingOverrides( + uint256 upkeepID + ) external view returns (AutomationRegistryBase2_3.BillingOverrides memory); function getBillingToken(uint256 upkeepID) external view returns (address); function getBillingTokenConfig(address token) external view returns (AutomationRegistryBase2_3.BillingConfig memory); function getBillingTokens() external view returns (address[] memory); @@ -276,6 +282,7 @@ interface IAutomationRegistryMaster2_3 { function getTransmitterInfo( address query ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee); + function getTransmittersWithPayees() external view returns (AutomationRegistryBase2_3.TransmitterPayeeInfo[] memory); function getTriggerType(uint256 upkeepId) external pure returns (uint8); function getUpkeep(uint256 id) external view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory upkeepInfo); function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory); @@ -355,6 +362,11 @@ interface AutomationRegistryBase2_3 { uint32 maxPerformDataSize; uint32 maxRevertDataSize; } + + struct TransmitterPayeeInfo { + address transmitterAddress; + address payeeAddress; + } } interface IAutomationV21PlusCommon { @@ -405,5 +417,5 @@ interface IAutomationV21PlusCommon { // THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: /* -[{"inputs":[{"internalType":"contract AutomationRegistryLogicA2_3","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InsufficientLinkLiquidity","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidFeed","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"MustSettleOffchain","type":"error"},{"inputs":[],"name":"MustSettleOnchain","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyFinanceAdmin","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"overrides","type":"tuple"}],"name":"BillingConfigOverridden","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"BillingConfigOverrideRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20Metadata","name":"token","type":"address"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"config","type":"tuple"}],"name":"BillingConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"ChainSpecificModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"payments","type":"uint256[]"}],"name":"NOPsSettledOffchain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"},{"internalType":"contract IERC20Metadata[]","name":"billingTokens","type":"address[]"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig[]","name":"billingConfigs","type":"tuple[]"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicB2_3","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicC2_3","name":"logicC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"removeBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"billingOverrides","type":"tuple"}],"name":"setBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"asset","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20Fees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkUSDFeed","type":"address"},{"internalType":"address","name":"nativeUSDFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"},{"internalType":"address","name":"allowedReadOnlyAddress","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"payoutMode","type":"uint8"},{"internalType":"address","name":"wrappedNativeTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableOffchainPayments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedReadOnlyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingToken","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"getBillingTokenConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBillingTokens","outputs":[{"internalType":"contract IERC20Metadata[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainModule","outputs":[{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFallbackNativePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHotVars","outputs":[{"components":[{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"reentrancyGuard","type":"bool"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.HotVars","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNativeUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumUpkeeps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPayoutMode","outputs":[{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerPerformByteGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReorgProtectionEnabled","outputs":[{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getReserveAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStorage","outputs":[{"components":[{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"}],"internalType":"struct AutomationRegistryBase2_3.Storage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmitCalldataFixedBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTransmitCalldataPerSignerBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWrappedNativeTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleNOPsOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"supportsBillingToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] +[{"inputs":[{"internalType":"contract AutomationRegistryLogicA2_3","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InsufficientLinkLiquidity","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidFeed","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"MustSettleOffchain","type":"error"},{"inputs":[],"name":"MustSettleOnchain","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyFinanceAdmin","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"overrides","type":"tuple"}],"name":"BillingConfigOverridden","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"BillingConfigOverrideRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20Metadata","name":"token","type":"address"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"config","type":"tuple"}],"name":"BillingConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"ChainSpecificModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"payments","type":"uint256[]"}],"name":"NOPsSettledOffchain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"},{"internalType":"contract IERC20Metadata[]","name":"billingTokens","type":"address[]"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig[]","name":"billingConfigs","type":"tuple[]"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicB2_3","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicC2_3","name":"logicC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"removeBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"billingOverrides","type":"tuple"}],"name":"setBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"asset","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20Fees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkUSDFeed","type":"address"},{"internalType":"address","name":"nativeUSDFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"},{"internalType":"address","name":"allowedReadOnlyAddress","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"payoutMode","type":"uint8"},{"internalType":"address","name":"wrappedNativeTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableOffchainPayments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedReadOnlyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getBillingConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingOverrides","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingToken","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"getBillingTokenConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBillingTokens","outputs":[{"internalType":"contract IERC20Metadata[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainModule","outputs":[{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFallbackNativePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHotVars","outputs":[{"components":[{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"reentrancyGuard","type":"bool"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.HotVars","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNativeUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumUpkeeps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPayoutMode","outputs":[{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerPerformByteGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReorgProtectionEnabled","outputs":[{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getReserveAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStorage","outputs":[{"components":[{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"}],"internalType":"struct AutomationRegistryBase2_3.Storage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmitCalldataFixedBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTransmitCalldataPerSignerBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmittersWithPayees","outputs":[{"components":[{"internalType":"address","name":"transmitterAddress","type":"address"},{"internalType":"address","name":"payeeAddress","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.TransmitterPayeeInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWrappedNativeTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleNOPsOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"supportsBillingToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] */ diff --git a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol index 19e1cdc7460..3e7e489379e 100644 --- a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol +++ b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol @@ -703,6 +703,23 @@ contract SetConfig is SetUp { ); } + function testSetConfigOnTransmittersAndPayees() public { + AutomationRegistryBase2_3.TransmitterPayeeInfo[] memory transmitterPayeeInfos = registry + .getTransmittersWithPayees(); + assertEq(transmitterPayeeInfos.length, TRANSMITTERS.length); + + for (uint256 i = 0; i < transmitterPayeeInfos.length; i++) { + address transmitterAddress = transmitterPayeeInfos[i].transmitterAddress; + address payeeAddress = transmitterPayeeInfos[i].payeeAddress; + + address expectedTransmitter = TRANSMITTERS[i]; + address expectedPayee = PAYEES[i]; + + assertEq(transmitterAddress, expectedTransmitter); + assertEq(payeeAddress, expectedPayee); + } + } + function testSetConfigWithNewTransmittersSuccess() public { registry = deployRegistry(AutoBase.PayoutMode.OFF_CHAIN); diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryBase2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryBase2_3.sol index 275b25b28d0..62c72adffc4 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryBase2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryBase2_3.sol @@ -331,7 +331,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { * @member index of oracle in s_signersList/s_transmittersList * @member balance a node's balance in LINK * @member lastCollected the total balance at which the node last withdrew - @ @dev uint96 is safe for balance / last collected because transmitters are only ever paid in LINK + * @dev uint96 is safe for balance / last collected because transmitters are only ever paid in LINK */ struct Transmitter { bool active; @@ -340,6 +340,11 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { uint96 lastCollected; } + struct TransmitterPayeeInfo { + address transmitterAddress; + address payeeAddress; + } + struct Signer { bool active; // Index of oracle in s_signersList/s_transmittersList diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol index 546c85454f7..92a9ca1a648 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol @@ -582,4 +582,35 @@ contract AutomationRegistryLogicC2_3 is AutomationRegistryBase2_3 { function linkAvailableForPayment() public view returns (int256) { return _linkAvailableForPayment(); } + + /** + * @notice returns the BillingOverrides config for a given upkeep + */ + function getBillingOverrides(uint256 upkeepID) external view returns (BillingOverrides memory) { + return s_billingOverrides[upkeepID]; + } + + /** + * @notice returns the BillingConfig for a given billing token, this includes decimals and price feed etc + */ + function getBillingConfig(IERC20 billingToken) external view returns (BillingConfig memory) { + return s_billingConfigs[billingToken]; + } + + /** + * @notice returns all active transmitters with their associated payees + */ + function getTransmittersWithPayees() external view returns (TransmitterPayeeInfo[] memory) { + uint256 transmitterCount = s_transmittersList.length; + TransmitterPayeeInfo[] memory transmitters = new TransmitterPayeeInfo[](transmitterCount); + + for (uint256 i = 0; i < transmitterCount; i++) { + address transmitterAddress = s_transmittersList[i]; + address payeeAddress = s_transmitterPayees[transmitterAddress]; + + transmitters[i] = TransmitterPayeeInfo(transmitterAddress, payeeAddress); + } + + return transmitters; + } } diff --git a/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go b/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go index a72ff506c90..cdbb52883ff 100644 --- a/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go +++ b/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go @@ -89,6 +89,11 @@ type AutomationRegistryBase23Storage struct { MaxRevertDataSize uint32 } +type AutomationRegistryBase23TransmitterPayeeInfo struct { + TransmitterAddress common.Address + PayeeAddress common.Address +} + type IAutomationV21PlusCommonOnchainConfigLegacy struct { PaymentPremiumPPB uint32 FlatFeeMicroLink uint32 @@ -134,7 +139,7 @@ type IAutomationV21PlusCommonUpkeepInfoLegacy struct { } var IAutomationRegistryMaster23MetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"acceptPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"acceptUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"addFunds\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"cancelUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"checkCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerData\",\"type\":\"bytes\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"disableOffchainPayments\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"executeCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveUpkeepIDs\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"getAdminPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowedReadOnlyAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAutomationForwarderLogic\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getBillingTokenConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBillingTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCancellationDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainModule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConditionalGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFallbackNativePrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFastGasFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getHotVars\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuard\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.HotVars\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLogGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMaxPaymentForGas\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"maxPayment\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalanceForUpkeep\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"minBalance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNativeUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumUpkeeps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPayoutMode\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"}],\"name\":\"getPeerRegistryMigrationPermission\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerPerformByteGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerSignerGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReorgProtectionEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getReserveAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getSignerInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"ownerLinkBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"expectedLinkBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"numUpkeeps\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"latestConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"internalType\":\"structIAutomationV21PlusCommon.StateLegacy\",\"name\":\"state\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"paymentPremiumPPB\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"flatFeeMicroLink\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint96\",\"name\":\"minUpkeepSpend\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"}],\"internalType\":\"structIAutomationV21PlusCommon.OnchainConfigLegacy\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStorage\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistryBase2_3.Storage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataFixedBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataPerSignerBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getTransmitterInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"lastCollected\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getTriggerType\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getUpkeep\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"maxValidBlocknumber\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"lastPerformedBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"amountSpent\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structIAutomationV21PlusCommon.UpkeepInfoLegacy\",\"name\":\"upkeepInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepTriggerConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNativeTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"hasDedupKey\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"migrateUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"pauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedUpkeeps\",\"type\":\"bytes\"}],\"name\":\"receiveUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"removeBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setAdminPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"billingOverrides\",\"type\":\"tuple\"}],\"name\":\"setBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfigBytes\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"onchainConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"address[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig[]\",\"name\":\"billingConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConfigTypeSafe\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"setPayees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"permission\",\"type\":\"uint8\"}],\"name\":\"setPeerRegistryMigrationPermission\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"setUpkeepCheckData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"}],\"name\":\"setUpkeepGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"name\":\"setUpkeepOffchainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"settleNOPsOffchain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"simulatePerformUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"supportsBillingToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"unpauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"upkeepVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20Fees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawPayment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"acceptPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"acceptUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"addFunds\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"cancelUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"checkCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerData\",\"type\":\"bytes\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"disableOffchainPayments\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"executeCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveUpkeepIDs\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"getAdminPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowedReadOnlyAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAutomationForwarderLogic\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getBillingConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingOverrides\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getBillingTokenConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBillingTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCancellationDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainModule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConditionalGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFallbackNativePrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFastGasFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getHotVars\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuard\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.HotVars\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLogGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMaxPaymentForGas\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"maxPayment\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalanceForUpkeep\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"minBalance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNativeUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumUpkeeps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPayoutMode\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"}],\"name\":\"getPeerRegistryMigrationPermission\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerPerformByteGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerSignerGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReorgProtectionEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getReserveAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getSignerInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"ownerLinkBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"expectedLinkBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"numUpkeeps\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"latestConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"internalType\":\"structIAutomationV21PlusCommon.StateLegacy\",\"name\":\"state\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"paymentPremiumPPB\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"flatFeeMicroLink\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint96\",\"name\":\"minUpkeepSpend\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"}],\"internalType\":\"structIAutomationV21PlusCommon.OnchainConfigLegacy\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStorage\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistryBase2_3.Storage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataFixedBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataPerSignerBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getTransmitterInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"lastCollected\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmittersWithPayees\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transmitterAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payeeAddress\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.TransmitterPayeeInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getTriggerType\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getUpkeep\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"maxValidBlocknumber\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"lastPerformedBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"amountSpent\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structIAutomationV21PlusCommon.UpkeepInfoLegacy\",\"name\":\"upkeepInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepTriggerConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNativeTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"hasDedupKey\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"migrateUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"pauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedUpkeeps\",\"type\":\"bytes\"}],\"name\":\"receiveUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"removeBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setAdminPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"billingOverrides\",\"type\":\"tuple\"}],\"name\":\"setBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfigBytes\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"onchainConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"address[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig[]\",\"name\":\"billingConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConfigTypeSafe\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"setPayees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"permission\",\"type\":\"uint8\"}],\"name\":\"setPeerRegistryMigrationPermission\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"setUpkeepCheckData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"}],\"name\":\"setUpkeepGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"name\":\"setUpkeepOffchainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"settleNOPsOffchain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"simulatePerformUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"supportsBillingToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"unpauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"upkeepVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20Fees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawPayment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", } var IAutomationRegistryMaster23ABI = IAutomationRegistryMaster23MetaData.ABI @@ -489,6 +494,50 @@ func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23CallerSession) Ge return _IAutomationRegistryMaster23.Contract.GetBalance(&_IAutomationRegistryMaster23.CallOpts, id) } +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Caller) GetBillingConfig(opts *bind.CallOpts, billingToken common.Address) (AutomationRegistryBase23BillingConfig, error) { + var out []interface{} + err := _IAutomationRegistryMaster23.contract.Call(opts, &out, "getBillingConfig", billingToken) + + if err != nil { + return *new(AutomationRegistryBase23BillingConfig), err + } + + out0 := *abi.ConvertType(out[0], new(AutomationRegistryBase23BillingConfig)).(*AutomationRegistryBase23BillingConfig) + + return out0, err + +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Session) GetBillingConfig(billingToken common.Address) (AutomationRegistryBase23BillingConfig, error) { + return _IAutomationRegistryMaster23.Contract.GetBillingConfig(&_IAutomationRegistryMaster23.CallOpts, billingToken) +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23CallerSession) GetBillingConfig(billingToken common.Address) (AutomationRegistryBase23BillingConfig, error) { + return _IAutomationRegistryMaster23.Contract.GetBillingConfig(&_IAutomationRegistryMaster23.CallOpts, billingToken) +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Caller) GetBillingOverrides(opts *bind.CallOpts, upkeepID *big.Int) (AutomationRegistryBase23BillingOverrides, error) { + var out []interface{} + err := _IAutomationRegistryMaster23.contract.Call(opts, &out, "getBillingOverrides", upkeepID) + + if err != nil { + return *new(AutomationRegistryBase23BillingOverrides), err + } + + out0 := *abi.ConvertType(out[0], new(AutomationRegistryBase23BillingOverrides)).(*AutomationRegistryBase23BillingOverrides) + + return out0, err + +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Session) GetBillingOverrides(upkeepID *big.Int) (AutomationRegistryBase23BillingOverrides, error) { + return _IAutomationRegistryMaster23.Contract.GetBillingOverrides(&_IAutomationRegistryMaster23.CallOpts, upkeepID) +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23CallerSession) GetBillingOverrides(upkeepID *big.Int) (AutomationRegistryBase23BillingOverrides, error) { + return _IAutomationRegistryMaster23.Contract.GetBillingOverrides(&_IAutomationRegistryMaster23.CallOpts, upkeepID) +} + func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Caller) GetBillingToken(opts *bind.CallOpts, upkeepID *big.Int) (common.Address, error) { var out []interface{} err := _IAutomationRegistryMaster23.contract.Call(opts, &out, "getBillingToken", upkeepID) @@ -1201,6 +1250,28 @@ func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23CallerSession) Ge return _IAutomationRegistryMaster23.Contract.GetTransmitterInfo(&_IAutomationRegistryMaster23.CallOpts, query) } +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Caller) GetTransmittersWithPayees(opts *bind.CallOpts) ([]AutomationRegistryBase23TransmitterPayeeInfo, error) { + var out []interface{} + err := _IAutomationRegistryMaster23.contract.Call(opts, &out, "getTransmittersWithPayees") + + if err != nil { + return *new([]AutomationRegistryBase23TransmitterPayeeInfo), err + } + + out0 := *abi.ConvertType(out[0], new([]AutomationRegistryBase23TransmitterPayeeInfo)).(*[]AutomationRegistryBase23TransmitterPayeeInfo) + + return out0, err + +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Session) GetTransmittersWithPayees() ([]AutomationRegistryBase23TransmitterPayeeInfo, error) { + return _IAutomationRegistryMaster23.Contract.GetTransmittersWithPayees(&_IAutomationRegistryMaster23.CallOpts) +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23CallerSession) GetTransmittersWithPayees() ([]AutomationRegistryBase23TransmitterPayeeInfo, error) { + return _IAutomationRegistryMaster23.Contract.GetTransmittersWithPayees(&_IAutomationRegistryMaster23.CallOpts) +} + func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Caller) GetTriggerType(opts *bind.CallOpts, upkeepId *big.Int) (uint8, error) { var out []interface{} err := _IAutomationRegistryMaster23.contract.Call(opts, &out, "getTriggerType", upkeepId) @@ -7239,6 +7310,10 @@ type IAutomationRegistryMaster23Interface interface { GetBalance(opts *bind.CallOpts, id *big.Int) (*big.Int, error) + GetBillingConfig(opts *bind.CallOpts, billingToken common.Address) (AutomationRegistryBase23BillingConfig, error) + + GetBillingOverrides(opts *bind.CallOpts, upkeepID *big.Int) (AutomationRegistryBase23BillingOverrides, error) + GetBillingToken(opts *bind.CallOpts, upkeepID *big.Int) (common.Address, error) GetBillingTokenConfig(opts *bind.CallOpts, token common.Address) (AutomationRegistryBase23BillingConfig, error) @@ -7307,6 +7382,8 @@ type IAutomationRegistryMaster23Interface interface { error) + GetTransmittersWithPayees(opts *bind.CallOpts) ([]AutomationRegistryBase23TransmitterPayeeInfo, error) + GetTriggerType(opts *bind.CallOpts, upkeepId *big.Int) (uint8, error) GetUpkeep(opts *bind.CallOpts, id *big.Int) (IAutomationV21PlusCommonUpkeepInfoLegacy, error) diff --git a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 6af70fd8f03..461b083fbfb 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 @@ -31,7 +31,7 @@ dummy_protocol_wrapper: ../../contracts/solc/v0.8.16/DummyProtocol/DummyProtocol gas_wrapper: ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.bin 4a5dcdac486d18fcd58e3488c15c1710ae76b977556a3f3191bd269a4bc75723 gas_wrapper_mock: ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.bin a9b08f18da59125c6fc305855710241f3d35161b8b9f3e3f635a7b1d5c6da9c8 i_automation_registry_master_wrapper_2_2: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster/IAutomationRegistryMaster.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster/IAutomationRegistryMaster.bin 9ff7087179f89f9b05964ebc3e71332fce11f1b8e85058f7b16b3bc0dd6fb96b -i_automation_registry_master_wrapper_2_3: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.bin fbfa3f5d78a357ecb7a1bc597c629ff30d42fedc48ba7f57e1622a6302d36523 +i_automation_registry_master_wrapper_2_3: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.bin 19f51996d05341f1229f21be26b5d72ff58e321f0b6da69c260f768e4622ae8e i_automation_v21_plus_common: ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.abi ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.bin e8a601ec382c0a2e83c49759de13b0622b5e04e6b95901e96a1e9504329e594c i_chain_module: ../../contracts/solc/v0.8.19/IChainModule/IChainModule.abi ../../contracts/solc/v0.8.19/IChainModule/IChainModule.bin 383611981c86c70522f41b8750719faacc7d7933a22849d5004799ebef3371fa i_keeper_registry_master_wrapper_2_1: ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.abi ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.bin ee0f150b3afbab2df3d24ff3f4c87851efa635da30db04cd1f70cb4e185a1781 From 7ec1d5b7abb51e100f7a6a48662e33703a589ecb Mon Sep 17 00:00:00 2001 From: Lei Date: Wed, 24 Apr 2024 16:46:16 -0700 Subject: [PATCH 09/34] update reserve amount of LINK after offchain settlement (#12916) --- .changeset/witty-icons-rhyme.md | 5 +++++ contracts/.changeset/poor-panthers-build.md | 5 +++++ .../v0.8/automation/dev/test/AutomationRegistry2_3.t.sol | 6 ++++++ .../automation/dev/v2_3/AutomationRegistryLogicC2_3.sol | 7 +++++++ 4 files changed, 23 insertions(+) create mode 100644 .changeset/witty-icons-rhyme.md create mode 100644 contracts/.changeset/poor-panthers-build.md diff --git a/.changeset/witty-icons-rhyme.md b/.changeset/witty-icons-rhyme.md new file mode 100644 index 00000000000..25d9cf3b1d3 --- /dev/null +++ b/.changeset/witty-icons-rhyme.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +offchain settlement fix #bugfix diff --git a/contracts/.changeset/poor-panthers-build.md b/contracts/.changeset/poor-panthers-build.md new file mode 100644 index 00000000000..2c21cae5d7a --- /dev/null +++ b/contracts/.changeset/poor-panthers-build.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +Offchain settlement fix #bugfix diff --git a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol index 3e7e489379e..03138696436 100644 --- a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol +++ b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol @@ -940,6 +940,9 @@ contract NOPsSettlement is SetUp { assertEq(i, index); assertEq(0, balance); } + + // after the offchain settlement, the total reserve amount of LINK should be 0 + assertEq(registry.getReserveAmount(address(linkToken)), 0); } function testSettleNOPsOffchainForDeactivatedTransmittersSuccess() public { @@ -1035,6 +1038,9 @@ contract NOPsSettlement is SetUp { assertEq(i, index); assertEq(0, balance); } + + // after the offchain settlement, the total reserve amount of LINK should be 0 + assertEq(registry.getReserveAmount(address(linkToken)), 0); } function testDisableOffchainPaymentsRevertDueToUnauthorizedCaller() public { diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol index 92a9ca1a648..4048227f111 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol @@ -166,6 +166,7 @@ contract AutomationRegistryLogicC2_3 is AutomationRegistryBase2_3 { uint256 length = activeTransmittersLength + deactivatedTransmittersLength; uint256[] memory payments = new uint256[](length); address[] memory payees = new address[](length); + for (uint256 i = 0; i < activeTransmittersLength; i++) { address transmitterAddr = s_transmittersList[i]; uint96 balance = _updateTransmitterBalanceFromPool( @@ -173,18 +174,24 @@ contract AutomationRegistryLogicC2_3 is AutomationRegistryBase2_3 { s_hotVars.totalPremium, uint96(activeTransmittersLength) ); + payments[i] = balance; payees[i] = s_transmitterPayees[transmitterAddr]; s_transmitters[transmitterAddr].balance = 0; } + for (uint256 i = 0; i < deactivatedTransmittersLength; i++) { address deactivatedAddr = s_deactivatedTransmitters.at(i); Transmitter memory transmitter = s_transmitters[deactivatedAddr]; + payees[i + activeTransmittersLength] = s_transmitterPayees[deactivatedAddr]; payments[i + activeTransmittersLength] = transmitter.balance; s_transmitters[deactivatedAddr].balance = 0; } + // reserve amount of LINK is reset to 0 since no user deposits of LINK are expected in offchain mode + s_reserveAmounts[IERC20(address(i_link))] = 0; + for (uint256 idx = s_deactivatedTransmitters.length(); idx > 0; idx--) { s_deactivatedTransmitters.remove(s_deactivatedTransmitters.at(idx - 1)); } From b65f2e09602f4a85e6d968193cf31eb4105949c0 Mon Sep 17 00:00:00 2001 From: Radek Scheibinger Date: Thu, 25 Apr 2024 10:54:07 +0200 Subject: [PATCH 10/34] Cleanup chainlink-cluster chart (#12950) * Cleanup chainlink-cluster chart CRIB chainlink-cluster chart has moved to internal repo. Deleting chart and integrating devspace config with internal repo via required ENV variable CHAINLINK_CLUSTER_HELM_CHART_URI * Delete helm related workflows and helm lint configs * fix reference to the go code which is now under crib directory * login to helm registry --- .ct.yml | 10 - .github/workflows/helm-chart-publish.yml | 41 -- .github/workflows/helm-chart.yml | 37 -- .gitignore | 1 - GNUmakefile | 4 +- charts/chainlink-cluster/.gitignore | 7 - charts/chainlink-cluster/.helmignore | 25 - charts/chainlink-cluster/Chart.lock | 15 - charts/chainlink-cluster/Chart.yaml | 22 - charts/chainlink-cluster/README.md | 174 ------- .../templates/chainlink-cm.yaml | 77 --- .../templates/chainlink-db-deployment.yaml | 154 ------ .../templates/chainlink-db-networkpolicy.yaml | 21 - .../templates/chainlink-db-service.yaml | 18 - .../templates/chainlink-node-deployment.yaml | 130 ------ .../chainlink-node-networkpolicy.yaml | 18 - .../templates/chainlink-node-service.yaml | 20 - .../templates/chainlink-pod-monitor.yaml | 18 - .../templates/chainlink-secret.yaml | 14 - .../templates/geth-config-map.yaml | 155 ------- .../templates/geth-deployment.yaml | 130 ------ .../templates/geth-networkpolicy.yaml | 25 - .../templates/geth-service.yaml | 21 - .../chainlink-cluster/templates/ingress.yaml | 43 -- .../templates/mockserver-networkpolicy.yaml | 21 - .../templates/networkpolicy-default.yaml | 43 -- .../templates/tests/test-connection.yaml | 15 - charts/chainlink-cluster/values.yaml | 439 ------------------ crib/.env.example | 4 + crib/devspace.yaml | 4 +- crib/scripts/check_env_vars.sh | 1 + crib/setup.sh | 27 +- .../values-profiles/README.md | 0 .../values-profiles/values-dev.yaml.example | 0 lintconf.yaml | 46 -- 35 files changed, 33 insertions(+), 1747 deletions(-) delete mode 100644 .ct.yml delete mode 100644 .github/workflows/helm-chart-publish.yml delete mode 100644 .github/workflows/helm-chart.yml delete mode 100644 charts/chainlink-cluster/.gitignore delete mode 100644 charts/chainlink-cluster/.helmignore delete mode 100644 charts/chainlink-cluster/Chart.lock delete mode 100644 charts/chainlink-cluster/Chart.yaml delete mode 100644 charts/chainlink-cluster/README.md delete mode 100644 charts/chainlink-cluster/templates/chainlink-cm.yaml delete mode 100644 charts/chainlink-cluster/templates/chainlink-db-deployment.yaml delete mode 100644 charts/chainlink-cluster/templates/chainlink-db-networkpolicy.yaml delete mode 100644 charts/chainlink-cluster/templates/chainlink-db-service.yaml delete mode 100644 charts/chainlink-cluster/templates/chainlink-node-deployment.yaml delete mode 100644 charts/chainlink-cluster/templates/chainlink-node-networkpolicy.yaml delete mode 100644 charts/chainlink-cluster/templates/chainlink-node-service.yaml delete mode 100644 charts/chainlink-cluster/templates/chainlink-pod-monitor.yaml delete mode 100644 charts/chainlink-cluster/templates/chainlink-secret.yaml delete mode 100644 charts/chainlink-cluster/templates/geth-config-map.yaml delete mode 100644 charts/chainlink-cluster/templates/geth-deployment.yaml delete mode 100644 charts/chainlink-cluster/templates/geth-networkpolicy.yaml delete mode 100644 charts/chainlink-cluster/templates/geth-service.yaml delete mode 100644 charts/chainlink-cluster/templates/ingress.yaml delete mode 100644 charts/chainlink-cluster/templates/mockserver-networkpolicy.yaml delete mode 100644 charts/chainlink-cluster/templates/networkpolicy-default.yaml delete mode 100644 charts/chainlink-cluster/templates/tests/test-connection.yaml delete mode 100644 charts/chainlink-cluster/values.yaml rename {charts/chainlink-cluster => crib}/values-profiles/README.md (100%) rename {charts/chainlink-cluster => crib}/values-profiles/values-dev.yaml.example (100%) delete mode 100644 lintconf.yaml diff --git a/.ct.yml b/.ct.yml deleted file mode 100644 index 18a6afe861d..00000000000 --- a/.ct.yml +++ /dev/null @@ -1,10 +0,0 @@ -# See: https://github.com/helm/chart-testing -target-branch: develop -chart-dirs: 'charts' -check-version-increment: false -validate-maintainers: false -charts-repos: - - mockserver=https://www.mock-server.com - - opentelemetry-collector=https://open-telemetry.github.io/opentelemetry-helm-charts - - tempo=https://grafana.github.io/helm-charts - - grafana=https://grafana.github.io/helm-charts diff --git a/.github/workflows/helm-chart-publish.yml b/.github/workflows/helm-chart-publish.yml deleted file mode 100644 index 927ed4b0166..00000000000 --- a/.github/workflows/helm-chart-publish.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Helm Publish - -on: - workflow_dispatch: - -jobs: - helm_release: - runs-on: ubuntu-latest - environment: build-develop - permissions: - id-token: write - contents: read - steps: - - name: Checkout repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - - name: Configure aws credentials - uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 - with: - role-to-assume: ${{ secrets.AWS_ROLE_ARN_GATI }} - role-duration-seconds: ${{ secrets.AWS_ROLE_DURATION_SECONDS }} - aws-region: ${{ secrets.AWS_REGION }} - mask-aws-account-id: true - role-session-name: helm-publish.helm-release - - - name: Get Github Token - id: get-gh-token - uses: smartcontractkit/chainlink-github-actions/github-app-token-issuer@5874ff7211cf5a5a2670bb010fbff914eaaae138 # v2.3.12 - with: - url: ${{ secrets.GATI_LAMBDA_FUNCTION_URL }} - - - name: Install Helm - uses: azure/setup-helm@b7246b12e77f7134dc2d460a3d5bad15bbe29390 # v4.1.0 - - - name: Run chart-releaser - uses: helm/chart-releaser-action@a917fd15b20e8b64b94d9158ad54cd6345335584 # v1.6.0 - with: - charts_dir: charts - config: .github/cr.yaml - env: - CR_TOKEN: "${{ steps.get-gh-token.outputs.access-token }}" diff --git a/.github/workflows/helm-chart.yml b/.github/workflows/helm-chart.yml deleted file mode 100644 index f0dd25c5dbb..00000000000 --- a/.github/workflows/helm-chart.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Helm Chart - -on: - pull_request: - paths: - - "charts/**" - - ".github/workflows/helm-chart.yml" - -jobs: - ci-lint-helm-charts: - runs-on: ubuntu-latest - steps: - - name: ci-lint-helm-charts - uses: smartcontractkit/.github/actions/ci-lint-charts@7fa39741b11e66ed59f8aad786d4b9356c389f3f # ci-lint-charts@0.2.0 - with: - # chart testing inputs - chart-testing-extra-args: "--lint-conf=lintconf.yaml" - charts-dir: charts/chainlink-cluster - # grafana inputs - metrics-job-name: ci-lint-helm-charts - gc-basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - gc-host: ${{ secrets.GRAFANA_INTERNAL_HOST }} - gc-org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - - ci-kubeconform: - runs-on: ubuntu-latest - steps: - - name: ci-kubeconform - uses: smartcontractkit/.github/actions/ci-kubeconform@1ae8a9a984814c4daf50aa96f03be2cba0ef3fec # ci-kubeconform@0.2.0 - with: - # kubeform inputs - charts-dir: charts/chainlink-cluster - # grafana inputs - metrics-job-name: ci-kubeconform - gc-basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - gc-host: ${{ secrets.GRAFANA_INTERNAL_HOST }} - gc-org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} diff --git a/.gitignore b/.gitignore index b286c329292..ca388c85c2b 100644 --- a/.gitignore +++ b/.gitignore @@ -24,7 +24,6 @@ tools/clroot/db.sqlite3-wal .envrc .env* .dbenv -!charts/chainlink-cluster/.env.example !crib/.env.example !.github/actions/setup-postgres/.env .direnv diff --git a/GNUmakefile b/GNUmakefile index 524786585e9..48e15e39fb4 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -33,7 +33,7 @@ gomodtidy: ## Run go mod tidy on all modules. cd ./integration-tests && go mod tidy cd ./integration-tests/load && go mod tidy cd ./dashboard-lib && go mod tidy - cd ./charts/chainlink-cluster && go mod tidy + cd ./crib && go mod tidy .PHONY: docs docs: ## Install and run pkgsite to view Go docs @@ -96,7 +96,7 @@ generate: abigen codecgen mockery protoc ## Execute all go:generate commands. cd ./integration-tests && go generate -x ./... cd ./integration-tests/load && go generate -x ./... cd ./dashboard-lib && go generate -x ./... - cd ./charts/chainlink-cluster && go generate -x ./... + cd ./crib && go generate -x ./... .PHONY: testscripts testscripts: chainlink-test ## Install and run testscript against testdata/scripts/* files. diff --git a/charts/chainlink-cluster/.gitignore b/charts/chainlink-cluster/.gitignore deleted file mode 100644 index 9e704020530..00000000000 --- a/charts/chainlink-cluster/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# Helm -charts/ -requirements.lock -.rendered -values-profiles/* -!values-profiles/values-dev.yaml.example -!values-profiles/README.md \ No newline at end of file diff --git a/charts/chainlink-cluster/.helmignore b/charts/chainlink-cluster/.helmignore deleted file mode 100644 index b88381301b2..00000000000 --- a/charts/chainlink-cluster/.helmignore +++ /dev/null @@ -1,25 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ -.devspace/ -scripts/ diff --git a/charts/chainlink-cluster/Chart.lock b/charts/chainlink-cluster/Chart.lock deleted file mode 100644 index 11ebdfdf691..00000000000 --- a/charts/chainlink-cluster/Chart.lock +++ /dev/null @@ -1,15 +0,0 @@ -dependencies: -- name: mockserver - repository: https://www.mock-server.com - version: 5.14.0 -- name: opentelemetry-collector - repository: https://open-telemetry.github.io/opentelemetry-helm-charts - version: 0.82.0 -- name: tempo - repository: https://grafana.github.io/helm-charts - version: 1.7.2 -- name: grafana - repository: https://grafana.github.io/helm-charts - version: 7.3.2 -digest: sha256:37722063f68689c42ac1d6549ddfae4756370c1659b8ac1c0d7da8916c6fad3d -generated: "2024-04-23T17:49:50.347667-04:00" diff --git a/charts/chainlink-cluster/Chart.yaml b/charts/chainlink-cluster/Chart.yaml deleted file mode 100644 index d8d3dd98b22..00000000000 --- a/charts/chainlink-cluster/Chart.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: v2 -name: chainlink-cluster -description: Chainlink nodes cluster -version: 0.4.2 -appVersion: "2.6.0" -dependencies: - - name: mockserver - version: "5.14.0" - repository: "https://www.mock-server.com" - condition: mockserver.enabled - - name: opentelemetry-collector - version: "0.82.0" - repository: "https://open-telemetry.github.io/opentelemetry-helm-charts" - condition: opentelemetry-collector.enabled - - name: tempo - version: "1.7.2" - repository: "https://grafana.github.io/helm-charts" - condition: tempo.enabled - - name: grafana - version: "7.3.2" - repository: "https://grafana.github.io/helm-charts" - condition: grafana.enabled diff --git a/charts/chainlink-cluster/README.md b/charts/chainlink-cluster/README.md deleted file mode 100644 index 403ab9b876a..00000000000 --- a/charts/chainlink-cluster/README.md +++ /dev/null @@ -1,174 +0,0 @@ -# Chainlink cluster - -Example CL nodes cluster for system level tests -Install `kubefwd` (no nixpkg for it yet, planned) - -```sh -brew install txn2/tap/kubefwd -``` - -If you want to build images you need [docker](https://docs.docker.com/engine/install/) service running - -Enter the shell (from the root project dir) - -```sh -nix develop -``` - -# Develop - -## New cluster - -We are using [devspace](https://www.devspace.sh/docs/getting-started/installation?x0=3) - -Configure the cluster, see `deployments.app.helm.values` and [values.yaml](./values.yaml) comments for more details - -Set up your K8s access - -```sh -export DEVSPACE_IMAGE="..." -./setup.sh ${my-personal-namespace-name-crib} -``` - -Create a .env file based on the .env.sample file - -```sh -cp .env.sample .env -# Fill in the required values in .env -``` - -Build and deploy the current state of your repository - -```sh -devspace deploy -``` - -Default `ttl` is `72h`, use `ttl` command to update if you need more time - -Valid values are `1h`, `2m`, `3s`, etc. Go time format is invalid `1h2m3s` - -```sh -devspace run ttl ${namespace} 120h -``` - -If you want to deploy an image tag that is already available in ECR, use: - -```sh -devspace deploy --override-image-tag "" -``` - -If you want to deploy an image tag from a public ECR repo, use: - -```sh -export DEVSPACE_IMAGE=public.ecr.aws/chainlink/chainlink -devspace deploy --override-image-tag 2.9.0 -``` - -To apply custom TOML configuration specific for your nodes, create a `values-dev.yaml` file in the `./values-profiles` directory. Start by copying the example file: - -```sh -cp values-profiles/values-dev.yaml.example values-profiles/values-dev.yaml - -``` - -Then customize the values-dev.yaml file as needed. To use this configuration during deployment, pass the --profile local-dev flag: - -```sh -devspace deploy --profile local-dev -``` - -Forward ports to check UI or run tests - -```sh -devspace run connect ${my-personal-namespace-name-crib} -``` - -List ingress hostnames - -```sh -devspace run ingress-hosts -``` - -Destroy the cluster - -```sh -devspace purge -``` - -## Running load tests - -Check this [doc](../../integration-tests/load/ocr/README.md) - -If you used `devspace dev ...` always use `devspace reset pods` to switch the pods back - -# Helm - -If you would like to use `helm` directly, please uncomment data in `values.yaml` - -## Install from local files - -```sh -helm install -f values.yaml cl-cluster . -``` - -Forward all apps (in another terminal) - -```sh -sudo kubefwd svc -n cl-cluster -``` - -Then you can connect and run your tests - -## Install from release - -Add the repository - -```sh -helm repo add chainlink-cluster https://raw.githubusercontent.com/smartcontractkit/chainlink/helm-release/ -helm repo update -``` - -Set default namespace - -```sh -kubectl create ns cl-cluster -kubectl config set-context --current --namespace cl-cluster -``` - -## Create a new release - -Bump version in `Chart.yml` add your changes and add `helm_release` label to any PR to trigger a release - -## Helm Test - -```sh -helm test cl-cluster -``` - -## Uninstall - -```sh -helm uninstall cl-cluster -``` - -# Grafana dashboard - -We are using [Grabana](https://github.com/K-Phoen/grabana) lib to create dashboards programmatically - -You can also select dashboard platform in `INFRA_PLATFORM` either `kubernetes` or `docker` - -```sh -export LOKI_TENANT_ID=promtail -export LOKI_URL=... -export GRAFANA_URL=... -export GRAFANA_TOKEN=... -export PROMETHEUS_DATA_SOURCE_NAME=Thanos -export LOKI_DATA_SOURCE_NAME=Loki -export INFRA_PLATFORM=kubernetes -export GRAFANA_FOLDER=CRIB -export DASHBOARD_NAME=Core-Cluster-Load - -devspace run dashboard_deploy -``` - -Open Grafana folder `DashboardCoreDebug` and find dashboard `ChainlinkClusterDebug` diff --git a/charts/chainlink-cluster/templates/chainlink-cm.yaml b/charts/chainlink-cluster/templates/chainlink-cm.yaml deleted file mode 100644 index bd0c911331c..00000000000 --- a/charts/chainlink-cluster/templates/chainlink-cm.yaml +++ /dev/null @@ -1,77 +0,0 @@ -{{- if .Values.chainlink.enabled }} -{{- range $cfg := .Values.chainlink.nodes }} -apiVersion: v1 -kind: ConfigMap -metadata: - labels: - app: {{ $.Release.Name }}-{{ $cfg.name }}-cm - release: {{ $.Release.Name }} - name: {{ $.Release.Name }}-{{ $cfg.name }}-cm -data: - apicredentials: | - notreal@fakeemail.ch - fj293fbBnlQ!f9vNs - node-password: T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ - init.sql: | - CREATE - EXTENSION pg_stat_statements; - default.toml: | - {{- if (hasKey $cfg "toml") }} - {{ $cfg.toml | nindent 4 }} - {{- else if and (hasKey $.Values.chainlink.global "toml") $.Values.chainlink.global.toml }} - {{ $.Values.chainlink.global.toml | nindent 4 }} - {{- else }} - RootDir = './clroot' - [Log] - JSONConsole = true - Level = 'debug' - [WebServer] - AllowOrigins = '*' - SecureCookies = false - SessionTimeout = '999h0m0s' - [Feature] - FeedsManager = true - LogPoller = true - UICSAKeys = true - [OCR] - Enabled = true - DefaultTransactionQueueDepth = 0 - [P2P] - [P2P.V2] - Enabled = true - ListenAddresses = ['0.0.0.0:6690'] - AnnounceAddresses = ['0.0.0.0:6690'] - DeltaDial = '500ms' - DeltaReconcile = '5s' - {{- range $chainCfg := $.Values.geth.chains }} - [[EVM]] - ChainID = {{ $chainCfg.networkId | quote }} - MinContractPayment = '0' - AutoCreateKey = true - FinalityDepth = 1 - {{- if (hasKey $chainCfg "customEVMConfigToml") }} - {{- $chainCfg.customEVMConfigToml | nindent 4 }} - {{- end }} - [[EVM.Nodes]] - Name = 'node-{{ $chainCfg.networkId }}' - WSURL = 'ws://geth-{{ $chainCfg.networkId }}:8546' - HTTPURL = 'http://geth-{{ $chainCfg.networkId }}:8544' - {{- end }} - [WebServer.TLS] - HTTPSPort = 0 - {{- end }} - overrides.toml: | - {{- if (hasKey $cfg "overridesToml") }} - {{- $cfg.overridesToml | nindent 4 }} - {{- else if and (hasKey $.Values.chainlink.global "overridesToml") $.Values.chainlink.global.overridesToml }} - {{- $.Values.chainlink.global.overridesToml | nindent 4 }} - {{ else }} - {{- end }} - secrets.toml: | - {{ if (hasKey $cfg "secretsToml") }} - {{ $cfg.secretsToml | nindent 4 }} - {{ else }} - {{ end }} ---- -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/chainlink-db-deployment.yaml b/charts/chainlink-cluster/templates/chainlink-db-deployment.yaml deleted file mode 100644 index 0ca7c4afd71..00000000000 --- a/charts/chainlink-cluster/templates/chainlink-db-deployment.yaml +++ /dev/null @@ -1,154 +0,0 @@ -{{- if .Values.db.enabled }} -{{- range $cfg := .Values.chainlink.nodes }} -apiVersion: apps/v1 -{{ if $.Values.db.stateful }} -kind: StatefulSet -{{ else }} -kind: Deployment -{{ end }} -metadata: - name: {{ $.Release.Name }}-{{ $cfg.name }}-db - labels: - app: {{ $.Release.Name }}-db - instance: {{ $cfg.name }}-db - release: {{ $.Release.Name }} -spec: - {{ if $.Values.db.stateful }} - serviceName: {{ $.Release.Name }}-db-${{ $cfg.name }} - podManagementPolicy: Parallel - volumeClaimTemplates: - - metadata: - name: postgres - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: {{ .Values.db.capacity }} - {{ end }} - selector: - matchLabels: - app: {{ $.Release.Name }}-db - # Used for testing. - # havoc-component-group and havoc-network-group are used by "havoc" chaos testing tool - havoc-component-group: db - havoc-network-group: db - instance: {{ $cfg.name }}-db - release: {{ $.Release.Name }} - template: - metadata: - labels: - app: {{ $.Release.Name }}-db - # Used for testing. - # havoc-component-group and havoc-network-group are used by "havoc" chaos testing tool - havoc-component-group: db - havoc-network-group: db - instance: {{ $cfg.name }}-db - release: {{ $.Release.Name }} - {{- range $key, $value := $.Values.labels }} - {{ $key }}: {{ $value | quote }} - {{- end }} - annotations: - prometheus.io/scrape: 'true' - app.kubernetes.io/managed-by: "Helm" - meta.helm.sh/release-namespace: "{{ $.Release.Namespace }}" - {{- range $key, $value := $.Values.podAnnotations }} - {{ $key }}: {{ $value | quote }} - {{- end }} - spec: - volumes: - # TODO: breakout this config map into a separate one for the db. - - name: {{ $.Release.Name }}-{{ $cfg.name }}-cm - configMap: - name: {{ $.Release.Name }}-{{ $cfg.name }}-cm - securityContext: - {{- toYaml $.Values.db.podSecurityContext | nindent 8 }} - containers: - - name: chainlink-db - securityContext: - {{- toYaml $.Values.db.securityContext | nindent 12 }} - image: {{ default "postgres:11.15" $.Values.db.image }} - command: - - docker-entrypoint.sh - args: - - "-c" - - "shared_preload_libraries=pg_stat_statements" - - "-c" - - "pg_stat_statements.track=all" - ports: - - name: postgres - containerPort: 5432 - env: - - name: POSTGRES_DB - value: chainlink - - name: POSTGRES_PASSWORD - value: verylongdatabasepassword - - name: PGPASSWORD - value: verylongdatabasepassword - - name: PGUSER - value: postgres - lifecycle: - preStop: - exec: - command: [ "/bin/sh", "-c", "while $(psql -d chainlink -c \"SELECT COUNT(*) FROM pg_stat_activity WHERE datname = 'chainlink' AND state = 'active';\" -tA ); echo \"waiting for connection to become 0\"; sleep 10; fi; done" ] - livenessProbe: - exec: - command: - - pg_isready - - -U - - postgres - initialDelaySeconds: 1 - periodSeconds: 5 - timeoutSeconds: 10 - readinessProbe: - exec: - command: - - pg_isready - - -U - - postgres - initialDelaySeconds: 1 - periodSeconds: 5 - timeoutSeconds: 10 - startupProbe: - exec: - command: - - pg_isready - - -U - - postgres - initialDelaySeconds: 15 - periodSeconds: 5 - failureThreshold: 20 - {{ if (hasKey $.Values.db "resources") }} - resources: - requests: - memory: {{ default "256Mi" $.Values.db.resources.requests.memory }} - cpu: {{ default "250m" $.Values.db.resources.requests.cpu }} - limits: - memory: {{ default "256Mi" $.Values.db.resources.limits.memory }} - cpu: {{ default "250m" $.Values.db.resources.limits.cpu }} - {{ else }} - {{ end }} - volumeMounts: - - mountPath: /docker-entrypoint-initdb.d/init.sql - name: {{ $.Release.Name }}-{{ $cfg.name }}-cm - subPath: init.sql - {{ if $.Values.db.stateful }} - - mountPath: /var/lib/postgresql/data - name: postgres - subPath: postgres-db - {{ end }} -{{- with $.Values.nodeSelector }} - nodeSelector: - {{ toYaml . | indent 8 }} -{{- end }} -{{- with $.Values.affinity }} - affinity: - {{ toYaml . | indent 8 }} -{{- end }} -{{- with $.Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} -{{- end }} ---- -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/chainlink-db-networkpolicy.yaml b/charts/chainlink-cluster/templates/chainlink-db-networkpolicy.yaml deleted file mode 100644 index 53664884f26..00000000000 --- a/charts/chainlink-cluster/templates/chainlink-db-networkpolicy.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and .Values.db.enabled .Values.networkPolicies.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ $.Release.Name }}-db -spec: - podSelector: - matchLabels: - app: {{ $.Release.Name }}-db - policyTypes: - - Ingress - ingress: - - from: - # Allow all node pods to access the database pods. - - podSelector: - matchLabels: - app: {{ $.Release.Name }} - ports: - - protocol: TCP - port: 5432 -{{- end }} diff --git a/charts/chainlink-cluster/templates/chainlink-db-service.yaml b/charts/chainlink-cluster/templates/chainlink-db-service.yaml deleted file mode 100644 index 5ed7d0ca4dd..00000000000 --- a/charts/chainlink-cluster/templates/chainlink-db-service.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if .Values.db.enabled }} -{{- range $cfg := .Values.chainlink.nodes }} -apiVersion: v1 -kind: Service -metadata: - name: {{ $.Release.Name }}-db-{{ $cfg.name }} -spec: - selector: - app: {{ $.Release.Name }}-db - instance: {{ $cfg.name }}-db - release: {{ $.Release.Name }} - ports: - - protocol: TCP - port: 5432 - targetPort: 5432 ---- -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/chainlink-node-deployment.yaml b/charts/chainlink-cluster/templates/chainlink-node-deployment.yaml deleted file mode 100644 index e91a400967a..00000000000 --- a/charts/chainlink-cluster/templates/chainlink-node-deployment.yaml +++ /dev/null @@ -1,130 +0,0 @@ -{{- if .Values.chainlink.enabled }} -{{- range $index, $cfg := .Values.chainlink.nodes }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ if eq $index 0 }}{{ $.Release.Name }}-{{ $cfg.name }}-bootstrap{{ else }}{{ $.Release.Name }}-{{ $cfg.name }}{{ end }} - labels: - app: {{ $.Release.Name }} - instance: {{ $cfg.name }} - release: {{ $.Release.Name }} - {{- range $key, $value := $.Values.labels }} - {{ $key }}: {{ $value | quote }} - {{- end }} -spec: - strategy: - # Need to recreate the pod to deal with lease lock held by old pod. - type: Recreate - selector: - matchLabels: - app: {{ $.Release.Name }} - # Used for testing. - # havoc-component-group and havoc-network-group are used by "havoc" chaos testing tool - {{ if eq $index 0 }}{{ else }} - havoc-component-group: node - {{ end }} - {{ if eq $index 0 }}{{ else }} - havoc-network-group: {{ if gt $index 2 }}"1"{{ else }}"2"{{ end }} - {{ end }} - instance: {{ $cfg.name }} - release: {{ $.Release.Name }} - template: - metadata: - labels: - app: {{ $.Release.Name }} - # Used for testing. - # havoc-component-group and havoc-network-group are used by "havoc" chaos testing tool - {{ if eq $index 0 }}{{ else }} - havoc-component-group: node - {{ end }} - {{ if eq $index 0 }}{{ else }} - havoc-network-group: {{ if gt $index 2 }}"1"{{ else }}"2"{{ end }} - {{ end }} - - instance: {{ $cfg.name }} - release: {{ $.Release.Name }} - {{- range $key, $value := $.Values.labels }} - {{ $key }}: {{ $value | quote }} - {{- end }} - annotations: - prometheus.io/scrape: 'true' - {{- range $key, $value := $.Values.podAnnotations }} - {{ $key }}: {{ $value | quote }} - {{- end }} - spec: - volumes: - - name: {{ $.Release.Name }}-{{ $cfg.name }}-cm - configMap: - name: {{ $.Release.Name }}-{{ $cfg.name }}-cm - securityContext: - {{- toYaml $.Values.chainlink.podSecurityContext | nindent 8 }} - containers: - - name: node - securityContext: - {{- toYaml $.Values.chainlink.securityContext | nindent 12 }} - image: {{ default "public.ecr.aws/chainlink/chainlink" $cfg.image }} - imagePullPolicy: Always - command: [ "bash", "-c", "while ! pg_isready -U postgres --host {{ $.Release.Name }}-db-{{ $cfg.name }} --port 5432; do echo \"waiting for database to start\"; sleep 1; done && chainlink -c /etc/node-secrets-volume/default.toml -c /etc/node-secrets-volume/overrides.toml -secrets /etc/node-secrets-volume/secrets.toml node start -d -p /etc/node-secrets-volume/node-password -a /etc/node-secrets-volume/apicredentials --vrfpassword=/etc/node-secrets-volume/apicredentials" ] - ports: - - name: access - containerPort: {{ $.Values.chainlink.web_port }} - - name: p2p - containerPort: {{ $.Values.chainlink.p2p_port }} - env: - - name: CL_DATABASE_URL - value: postgresql://postgres:verylongdatabasepassword@{{ $.Release.Name }}-db-{{ $cfg.name }}/chainlink?sslmode=disable - - name: CL_DEV - value: "false" - {{- range $name, $value := $.Values.chainlink.extraEnvVars }} - - name: "{{ $name }}" - value: "{{ $value }}" - {{- end }} - volumeMounts: - - name: {{ $.Release.Name }}-{{ $cfg.name }}-cm - mountPath: /etc/node-secrets-volume/ - livenessProbe: - httpGet: - path: /health - port: {{ $.Values.chainlink.web_port }} - initialDelaySeconds: 1 - periodSeconds: 5 - timeoutSeconds: 10 - readinessProbe: - httpGet: - path: /health - port: {{ $.Values.chainlink.web_port }} - initialDelaySeconds: 1 - periodSeconds: 5 - timeoutSeconds: 10 - startupProbe: - httpGet: - path: / - port: {{ $.Values.chainlink.web_port }} - initialDelaySeconds: 15 - periodSeconds: 5 - failureThreshold: 20 - {{ if (hasKey $cfg "resources") }} - resources: - requests: - memory: {{ default "1024Mi" $cfg.resources.requests.memory }} - cpu: {{ default "300m" $cfg.resources.requests.cpu }} - limits: - memory: {{ default "1024Mi" $cfg.resources.limits.memory }} - cpu: {{ default "300m" $cfg.resources.limits.cpu }} - {{ else }} - {{ end }} -{{- with $.Values.nodeSelector }} - nodeSelector: - {{ toYaml . | indent 8 }} -{{- end }} -{{- with $.Values.affinity }} - affinity: - {{ toYaml . | indent 8 }} -{{- end }} -{{- with $.Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} -{{- end }} ---- -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/chainlink-node-networkpolicy.yaml b/charts/chainlink-cluster/templates/chainlink-node-networkpolicy.yaml deleted file mode 100644 index 8f465288767..00000000000 --- a/charts/chainlink-cluster/templates/chainlink-node-networkpolicy.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if and .Values.chainlink.enabled .Values.networkPolicies.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ $.Release.Name }}-node -spec: - podSelector: - matchLabels: - app: {{ $.Release.Name }} - policyTypes: - - Ingress - ingress: - # Allow all ingress traffic between the node pods. - - from: - - podSelector: - matchLabels: - app: {{ $.Release.Name }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/chainlink-node-service.yaml b/charts/chainlink-cluster/templates/chainlink-node-service.yaml deleted file mode 100644 index 71b9ca498d2..00000000000 --- a/charts/chainlink-cluster/templates/chainlink-node-service.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if .Values.chainlink.enabled }} -{{- range $cfg := .Values.chainlink.nodes }} -apiVersion: v1 -kind: Service -metadata: - name: {{ $.Release.Name }}-{{ $cfg.name }} -spec: - ports: - - name: node-port - port: {{ $.Values.chainlink.web_port }} - targetPort: {{ $.Values.chainlink.web_port }} - - name: p2p-port - port: {{ $.Values.chainlink.p2p_port }} - targetPort: {{ $.Values.chainlink.p2p_port }} - selector: - instance: {{ $cfg.name }} - type: ClusterIP ---- -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/chainlink-pod-monitor.yaml b/charts/chainlink-cluster/templates/chainlink-pod-monitor.yaml deleted file mode 100644 index bb8c5d2b1a6..00000000000 --- a/charts/chainlink-cluster/templates/chainlink-pod-monitor.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if and .Values.chainlink.enabled .Values.prometheusMonitor }} -apiVersion: monitoring.coreos.com/v1 -kind: PodMonitor -metadata: - name: {{ $.Release.Name }}-pod-monitor - labels: - release: grafana-agent -spec: - namespaceSelector: - matchNames: - - {{ $.Release.Namespace }} - podMetricsEndpoints: - - port: access - selector: - matchLabels: - app: {{ $.Release.Name }} -{{- end }} ---- \ No newline at end of file diff --git a/charts/chainlink-cluster/templates/chainlink-secret.yaml b/charts/chainlink-cluster/templates/chainlink-secret.yaml deleted file mode 100644 index f0531b16511..00000000000 --- a/charts/chainlink-cluster/templates/chainlink-secret.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- if .Values.chainlink.enabled }} -{{- range $cfg := .Values.chainlink.nodes }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ $.Release.Name }}-{{ $cfg.name }}node-creds-secret -type: Opaque -data: - nodepassword: VC50TEhrY213ZVBUL3AsXXNZdW50andIS0FzcmhtIzRlUnM0THVLSHd2SGVqV1lBQzJKUDRNOEhpbXdnbWJhWgo= - apicredentials: bm90cmVhbEBmYWtlZW1haWwuY2hudHdvY2hhaW5zCg== - node-password: VC50TEhrY213ZVBUL3AsXXNZdW50andIS0FzcmhtIzRlUnM0THVLSHd2SGVqV1lBQzJKUDRNOEhpbXdnbWJhWgo= ---- -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/geth-config-map.yaml b/charts/chainlink-cluster/templates/geth-config-map.yaml deleted file mode 100644 index 6a5f4bacc0d..00000000000 --- a/charts/chainlink-cluster/templates/geth-config-map.yaml +++ /dev/null @@ -1,155 +0,0 @@ -{{ if and (hasKey .Values "geth") .Values.geth.enabled }} -{{- range $cfg := .Values.geth.chains }} -apiVersion: v1 -kind: ConfigMap -metadata: - labels: - app: geth-{{ $cfg.networkId }}-cm - release: {{ $.Release.Name }} - name: geth-{{ $cfg.networkId }}-cm -data: - key1: | - {"address":"f39fd6e51aad88f6f4ce6ab8827279cfffb92266","crypto":{"cipher":"aes-128-ctr","ciphertext":"c36afd6e60b82d6844530bd6ab44dbc3b85a53e826c3a7f6fc6a75ce38c1e4c6","cipherparams":{"iv":"f69d2bb8cd0cb6274535656553b61806"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"80d5f5e38ba175b6b89acfc8ea62a6f163970504af301292377ff7baafedab53"},"mac":"f2ecec2c4d05aacc10eba5235354c2fcc3776824f81ec6de98022f704efbf065"},"id":"e5c124e9-e280-4b10-a27b-d7f3e516b408","version":3} - key2: | - {"address":"70997970c51812dc3a010c7d01b50e0d17dc79c8","crypto":{"cipher":"aes-128-ctr","ciphertext":"f8183fa00bc112645d3e23e29a233e214f7c708bf49d72750c08af88ad76c980","cipherparams":{"iv":"796d08e3e1f71bde89ed826abda96cda"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"03c864a22a1f7b06b1da12d8b93e024ac144f898285907c58b2abc135fc8a35c"},"mac":"5fe91b1a1821c0d9f85dfd582354ead9612e9a7e9adc38b06a2beff558c119ac"},"id":"d2cab765-5e30-42ae-bb91-f090d9574fae","version":3} - key3: | - {"address":"3c44cdddb6a900fa2b585dd299e03d12fa4293bc","crypto":{"cipher":"aes-128-ctr","ciphertext":"2cd6ab87086c47f343f2c4d957eace7986f3b3c87fc35a2aafbefb57a06d9f1c","cipherparams":{"iv":"4e16b6cd580866c1aa642fb4d7312c9b"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"0cabde93877f6e9a59070f9992f7a01848618263124835c90d4d07a0041fc57c"},"mac":"94b7776ea95b0ecd8406c7755acf17b389b7ebe489a8942e32082dfdc1f04f57"},"id":"ade1484b-a3bb-426f-9223-a1f5e3bde2e8","version":3} - key4: | - {"address":"90f79bf6eb2c4f870365e785982e1f101e93b906","crypto":{"cipher":"aes-128-ctr","ciphertext":"15144214d323871e00f7b205368128061c91b77a27b7deec935f8f5b734f0d42","cipherparams":{"iv":"bb22ba8051ef9f60abded7a9f4f2c6ae"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"07331ef3035567c00830b4e50d5dd68bc877974b4ce38cd42fef755be01556c9"},"mac":"2294eacadaf2761851814451d8c7dcca20a606a0344335d98f09403aba4e82ca"},"id":"96af8cc7-97e1-4bba-8968-632b034986c2","version":3} - key5: | - {"address":"15d34aaf54267db7d7c367839aaf71a00a2c6a65","crypto":{"cipher":"aes-128-ctr","ciphertext":"057878284a6c74d3ad99910adddd6b477b383837dbf2280efea585f0f0fdb012","cipherparams":{"iv":"e6eab29d60b526f305f8d47badf48687"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"dfdca8066d2486da5cb9a909d03744e2a8c6537930271e85e7cd8a5d952c0f22"},"mac":"f8352be41c9a06d69111ca4d8fcff0eef079b68b1173cad99803538991716c5d"},"id":"a35bb452-0d57-42d5-8d25-5a00a40a4db8","version":3} - key6: | - {"address":"9965507d1a55bcc2695c58ba16fb37d819b0a4dc","crypto":{"cipher":"aes-128-ctr","ciphertext":"5a73201500307c6aa98edd44d962b344a893768331454a61595ec848e738e9d2","cipherparams":{"iv":"5282de2b3e2b305019a2fed5c62f3383"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"6ad001831d097f175fff7d6cf61301e9620b32afd9a7a6437e6030af14576a96"},"mac":"0a55eddbd13c713aa8b8c4106b2fb62bc1d1e18e7177207a444f83a4d8426ed5"},"id":"27aed2b2-cb94-4d37-8819-b15219187bb5","version":3} - key7: | - {"address":"976ea74026e726554db657fa54763abd0c3a0aa9","crypto":{"cipher":"aes-128-ctr","ciphertext":"a6edf11e81b38e60a549696236cb9efc026e87adc45a9521ea7b2c45a2a9fbb9","cipherparams":{"iv":"82f4c79cd4b28a8585a9c78d758f832b"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"87400e16ecc320dadff85eccbf4dbaaea2dd91e50047e4aa391799bb319c1fd8"},"mac":"80c83dad05998db6c673a97096fcfad54636458f4a3c82483686b253f8cc9b69"},"id":"fc7d7694-6206-48fc-bb25-36b523f90df6","version":3} - key8: | - {"address":"14dc79964da2c08b23698b3d3cc7ca32193d9955","crypto":{"cipher":"aes-128-ctr","ciphertext":"410f258bc8b12a0250cba22cbc5e413534fcf90bf322ced6943189ad9e43b4b9","cipherparams":{"iv":"1dd6077a8bee9b3bf2ca90e6abc8a237"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"5d3358bf99bbcb82354f40e5501abf4336bc141ee05d8feed4fbe7eb8c08c917"},"mac":"9cd959fa1e8129a8deb86e0264ec81d6cde79b5a19ae259b7d00543c9037908a"},"id":"689d7ad2-fe46-4c09-9c2a-a50e607989b8","version":3} - key9: | - {"address":"23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f","crypto":{"cipher":"aes-128-ctr","ciphertext":"13dccac740314edea20d44e6f3592575bbcb739ec5892d635326cff3c386eb86","cipherparams":{"iv":"bf42d811cd41fa97ddcae3425f8c3211"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"d2fa67cbb5e86d5bf9a90e27b8747bac493614b45778d43e9da1c14e06b2401d"},"mac":"7d2797cf344704d8f36265238d3938e06952c78ab7dfcbac53dc7f472c93d933"},"id":"4c8e899e-80f0-4417-9b1e-c5e29049f1e7","version":3} - key10: | - {"address":"a0ee7a142d267c1f36714e4a8f75612f20a79720","crypto":{"cipher":"aes-128-ctr","ciphertext":"56bc8766f47aeafae74eea333e1e890a3776d7fae6c48cbdbffb270655ce050d","cipherparams":{"iv":"a66129e6a110b3ddf93b4355aa147c58"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"15c4e8bcc80920139eb236d91194825f1fce27dd2af281e0f2752d8a5dbc48bd"},"mac":"db01e720866ce8bb7897dfc7773e064003ad53429a79732ee769cf6d02273570"},"id":"87b2d76f-1b70-4e4f-8b2a-5d1915c1177c","version":3} - key11: | - {"address":"bcd4042de499d14e55001ccbb24a551f3b954096","crypto":{"cipher":"aes-128-ctr","ciphertext":"e455eda6e38d246c03b930f845adfc8721ca75e9f47135cd4c18dbc3e5c5440a","cipherparams":{"iv":"0b1a0a24acc1ad25b0f170f751c2cb27"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"69f324ed0787794878bf5f84d4dbbc70dec1274cad666399edc48640605f64c8"},"mac":"f07da09c460a69f943f5639545d2b3f72c1e9789f0421ad41d3078ea3db12c96"},"id":"7ec7bb3c-c486-4785-a4fc-f8f4b2fc7764","version":3} - key12: | - {"address":"71be63f3384f5fb98995898a86b02fb2426c5788","crypto":{"cipher":"aes-128-ctr","ciphertext":"4194377a05fd3d13e0a3155dad974a003fe5f7a3b5acb35d7d97c50daa8990d4","cipherparams":{"iv":"607670778baf62b1e86394cf1980487a"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"d63b890ad7f4fcc857681faabe9319dffc53893966ef0810bf64c4f319b0ffc5"},"mac":"bfaf924959e65c8030ece259d52ed52d5d21bd74f1a67ae545d4bb289a479e16"},"id":"0c6af842-384f-49b6-b5b7-199a1e05486b","version":3} - key13: | - {"address":"fabb0ac9d68b0b445fb7357272ff202c5651694a","crypto":{"cipher":"aes-128-ctr","ciphertext":"6bad79e57a9b80e1b2aa7292a2f72613615a43da2796abeac071ad06a2decff6","cipherparams":{"iv":"91f24b0da7179a0e62803cb2cba6bb49"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"153a063a0dcf7abe7fd730ba908d00856783f0814e1b684a6a08b519d5dbadda"},"mac":"b007d01324b2d05c9a0333e4fbf826681ee2f5ddb4007c6fab20ef923481ba8f"},"id":"fb09dfff-ac3b-46c5-8d88-f4549007977b","version":3} - key14: | - {"address":"1cbd3b2770909d4e10f157cabc84c7264073c9ec","crypto":{"cipher":"aes-128-ctr","ciphertext":"3a7b9d84afb8d6241974cf35a34cbce077aae04f4c0aea1730167c9d8266bd74","cipherparams":{"iv":"329b510bce6e63a53827a0c307c041b5"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"6648c7f4ed24d1134dcf5983a5ca4bc5ae16787f0813530d5ae4c9c61dd3623f"},"mac":"65098dcdaabfb404539aeeea20f41b24886f9d3a55b9a841e2769692e19b75e8"},"id":"2053c6ce-da95-44d2-af1f-1939319aaa45","version":3} - key15: | - {"address":"df3e18d64bc6a983f673ab319ccae4f1a57c7097","crypto":{"cipher":"aes-128-ctr","ciphertext":"ab5802ecd849b0931d822a59597f9b59277526c13dcf792d1f6771ff0a63c902","cipherparams":{"iv":"c10e50c9f7359d281bfddd90ffeee967"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"97848515d8c93caab641882fea9b1428de32a8cf006d998893d01c03a0c2f48c"},"mac":"a2c5fbf7f78e498ee4a8bb242b4a03d4fb77f4135218a5af1d4b99ebd8991c9d"},"id":"83fa51c4-48f7-4d1d-b368-c9bd9d8841ee","version":3} - key16: | - {"address":"cd3b766ccdd6ae721141f452c550ca635964ce71","crypto":{"cipher":"aes-128-ctr","ciphertext":"05f18b7afa63c3748f3c5c99c8f036df1295f7660380e3c6a3fc6252f40566aa","cipherparams":{"iv":"3346ffa57c1b04f678d373cce4e4383a"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"c21f4d22a2324039b3f7cd6dbfa757bc489fa676d700b3ee88d0e3b334698720"},"mac":"7762c08bb673333946e87c33108349d10850c559104e863c5b0826cd6e64df78"},"id":"67b3c79c-d696-4e1b-a381-d67553bc674b","version":3} - key17: | - {"address":"2546bcd3c84621e976d8185a91a922ae77ecec30","crypto":{"cipher":"aes-128-ctr","ciphertext":"accd54a6b3969a4aed305baa0cd35ce4b54dcc92d866ff8b3d23536609a282eb","cipherparams":{"iv":"93be3f925ddea06113b3dcac650e9b6b"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"092f7823a668981e14f715ae7352fa176461cddd94267f9dd6f23f9fe663ba9a"},"mac":"bb4792148205a4f0d8dfc5cd04725d0a4785a6d7e6ca0c208ffc0b005947821b"},"id":"368b24f6-6d1b-4fd5-a506-d73b5bb4aac8","version":3} - key18: | - {"address":"bda5747bfd65f08deb54cb465eb87d40e51b197e","crypto":{"cipher":"aes-128-ctr","ciphertext":"8bc3bf720dce7d010617edaf6db4ed35701c13ff67cd9dce742de77b4b4b3df0","cipherparams":{"iv":"50075ca52dd388719b27e3029f01a484"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"8e365100caeda20cc0a13c28517d62fc41d5cae1da4dae3fef51daf4b323da81"},"mac":"5ed7ad5aca897fd03ebeb08a7fcfa38d2eadc240b6eb6ad53f7c06c6ee9085de"},"id":"8b627671-46e5-4081-a25a-c928b135a87e","version":3} - key19: | - {"address":"dd2fd4581271e230360230f9337d5c0430bf44c0","crypto":{"cipher":"aes-128-ctr","ciphertext":"39c1bbd9c070465fb7828be95b3b0978482aab16b8b1f11db0022321bcaa9172","cipherparams":{"iv":"35bd60a818c50e65fee00031f0a33d8e"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"eecd539685126cfc1f444070d7528c5f570d71c48994118af8c50c316ef72a99"},"mac":"93224b4767a57a8cd394c37087f0dfc9393b381f09c45c5abc55cec5d719181f"},"id":"321978cb-f1bf-4790-8a29-5e5878f8dbb9","version":3} - key20: | - {"address":"8626f6940e2eb28930efb4cef49b2d1f2c9c1199","crypto":{"cipher":"aes-128-ctr","ciphertext":"8a3f1dc7b110c5ce59007f6e55fd7f055b41e518b1f34e93b4185aa44d8a1f92","cipherparams":{"iv":"02fe1b25039baf5abbdd448b932b2ab5"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"a75a6b250851f76f36132aad3ca944493b7d20a07bd4c7b1d8574596a240b35f"},"mac":"679d96ef17c9ac86960e61ced85eb551ba1895cfde2c8bb099e38dc1251a44f0"},"id":"5d3a08df-78f3-43e8-8978-75652502c962","version":3} - password.txt: | - init.sh: | - #!/bin/bash - if [ ! -d /chain/chain-data/keystore ]; then - echo "/chain/chain-data/keystore not found, running 'geth init'..." - geth init --datadir /chain/chain-data/ /chain/genesis.json - echo "...done!" - cp /chain/config/key* /chain/chain-data/keystore - fi - - cd /chain/chain-data && geth "$@" - genesis.json: | - { - "config": { - "chainId": {{ $cfg.networkId }}, - "homesteadBlock": 0, - "eip150Block": 0, - "eip155Block": 0, - "eip158Block": 0, - "eip160Block": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "petersburgBlock": 0, - "istanbulBlock": 0, - "muirGlacierBlock": 0, - "berlinBlock": 0, - "londonBlock": 0, - "clique": { - "period": 2, - "epoch": 30000 - } - }, - "nonce": "0x0000000000000042", - "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "1", - "coinbase": "0x3333333333333333333333333333333333333333", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "gasLimit": "8000000000", - "alloc": { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": { - "balance": "20000000000000000000000" - }, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": { - "balance": "20000000000000000000000" - }, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": { - "balance": "20000000000000000000000" - }, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": { - "balance": "20000000000000000000000" - }, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": { - "balance": "20000000000000000000000" - }, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": { - "balance": "20000000000000000000000" - }, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": { - "balance": "20000000000000000000000" - }, - "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955": { - "balance": "20000000000000000000000" - }, - "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f": { - "balance": "20000000000000000000000" - }, - "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720": { - "balance": "20000000000000000000000" - }, - "0xBcd4042DE499D14e55001CcbB24a551F3b954096": { - "balance": "20000000000000000000000" - }, - "0x71bE63f3384f5fb98995898A86B02Fb2426c5788": { - "balance": "20000000000000000000000" - }, - "0xFABB0ac9d68B0B445fB7357272Ff202C5651694a": { - "balance": "20000000000000000000000" - }, - "0x1CBd3b2770909D4e10f157cABC84C7264073C9Ec": { - "balance": "20000000000000000000000" - }, - "0xdF3e18d64BC6A983f673Ab319CCaE4f1a57C7097": { - "balance": "20000000000000000000000" - }, - "0xcd3B766CCDd6AE721141F452C550Ca635964ce71": { - "balance": "20000000000000000000000" - }, - "0x2546BcD3c84621e976D8185a91A922aE77ECEc30": { - "balance": "20000000000000000000000" - }, - "0xbDA5747bFD65F08deb54cb465eB87D40e51B197E": { - "balance": "20000000000000000000000" - }, - "0xdD2FD4581271e230360230F9337D5c0430Bf44C0": { - "balance": "20000000000000000000000" - }, - "0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199": { - "balance": "20000000000000000000000" - } - } - } ---- -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/geth-deployment.yaml b/charts/chainlink-cluster/templates/geth-deployment.yaml deleted file mode 100644 index 6eccdbd20b4..00000000000 --- a/charts/chainlink-cluster/templates/geth-deployment.yaml +++ /dev/null @@ -1,130 +0,0 @@ -{{ if and (hasKey .Values "geth") .Values.geth.enabled }} -{{- range $cfg := .Values.geth.chains }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: geth-{{ $cfg.networkId }} - labels: - app: geth - release: {{ $.Release.Name }} - instance: geth-{{ $cfg.networkId }} -spec: - selector: - matchLabels: - app: geth - release: {{ $.Release.Name }} - instance: geth-{{ $cfg.networkId }} - # Used for testing. - # havoc-component-group and havoc-network-group are used by "havoc" chaos testing tool - havoc-component-group: "blockchain" - havoc-network-group: "blockchain" - template: - metadata: - labels: - app: geth - instance: geth-{{ $cfg.networkId }} - release: {{ $.Release.Name }} - # Used for testing. - # havoc-component-group and havoc-network-group are used by "havoc" chaos testing tool - havoc-component-group: "blockchain" - havoc-network-group: "blockchain" - annotations: - {{- range $key, $value := $.Values.podAnnotations }} - {{ $key }}: {{ $value | quote }} - {{- end }} - spec: - volumes: - - name: configmap-volume - configMap: - name: geth-{{ $cfg.networkId }}-cm - - name: devchain-volume - emptyDir: {} - securityContext: - {{- toYaml $.Values.geth.podSecurityContext | nindent 8 }} - containers: - - name: geth-network - securityContext: - {{- toYaml $.Values.geth.securityContext | nindent 12 }} - image: "{{ default "ethereum/client-go" $.Values.geth.image }}:{{ default "stable" $.Values.geth.version }}" - command: [ "sh", "/chain/init.sh" ] - volumeMounts: - - name: devchain-volume - mountPath: /chain/chain-data - - name : configmap-volume - mountPath: /chain/genesis.json - subPath: genesis.json - - name : configmap-volume - mountPath: /chain/init.sh - subPath: init.sh - - name: configmap-volume - mountPath: /chain/config - args: - - '--password' - - '/chain/config/password.txt' - - '--datadir' - - '/chain/chain-data/' - - '--unlock' - - '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266' - - '--mine' - - '--miner.etherbase' - - '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266' - - '--ipcdisable' - - '--http.api' - - 'admin,debug,clique,eth,miner,net,personal,txpool,web3' - - '--http' - - '--http.vhosts' - - '*' - - '--http.addr' - - '0.0.0.0' - - '--http.port=8544' - - '--ws' - - '--ws.origins' - - '*' - - '--ws.addr' - - '0.0.0.0' - - '--ws.port=8546' - - '--graphql' - - '-graphql.corsdomain' - - '*' - - '--allow-insecure-unlock' - - '--rpc.allow-unprotected-txs' - - '--http.corsdomain' - - '*' - - '--vmdebug' - - '--networkid={{ $cfg.networkId }}' - - '--rpc.txfeecap' - - '0' - - '--dev.period' - - '{{ $.Values.geth.blocktime }}' - - '--miner.gasprice' - - '10000000000' - ports: - - name: http-rpc - containerPort: 8544 - - name: ws-rpc - containerPort: 8546 - {{ if (hasKey $.Values.geth "resources") }} - resources: - requests: - memory: {{ default "1024Mi" $.Values.geth.resources.requests.memory }} - cpu: {{ default "1000m" $.Values.geth.resources.requests.cpu }} - limits: - memory: {{ default "1024Mi" $.Values.geth.resources.limits.memory }} - cpu: {{ default "1000m" $.Values.geth.resources.limits.cpu }} - {{ else }} - {{ end }} -{{- with $.Values.nodeSelector }} - nodeSelector: - {{ toYaml . | indent 8 }} -{{- end }} -{{- with $.Values.affinity }} - affinity: - {{ toYaml . | indent 8 }} -{{- end }} -{{- with $.Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} -{{- end }} ---- -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/geth-networkpolicy.yaml b/charts/chainlink-cluster/templates/geth-networkpolicy.yaml deleted file mode 100644 index 2a37a92aaaa..00000000000 --- a/charts/chainlink-cluster/templates/geth-networkpolicy.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{ if and (hasKey .Values "geth") .Values.geth.enabled }} -{{- if .Values.networkPolicies.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ $.Release.Name }}-geth -spec: - podSelector: - matchLabels: - app: geth - policyTypes: - - Ingress - ingress: - - from: - # Allow http and websocket connections from the node pods. - - podSelector: - matchLabels: - app: {{ $.Release.Name }} - ports: - - protocol: TCP - port: 8544 - - protocol: TCP - port: 8546 -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/geth-service.yaml b/charts/chainlink-cluster/templates/geth-service.yaml deleted file mode 100644 index 63a86a3d1d7..00000000000 --- a/charts/chainlink-cluster/templates/geth-service.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{ if and (hasKey .Values "geth") .Values.geth.enabled }} -{{- range $cfg := .Values.geth.chains }} -apiVersion: v1 -kind: Service -metadata: - name: geth-{{ $cfg.networkId }} -spec: - selector: - instance: geth-{{ $cfg.networkId }} - release: {{ $.Release.Name }} - ports: - - name: ws-rpc - port: {{ default "8546" $.Values.geth.wsrpc_port}} - targetPort: ws-rpc - - name: http-rpc - port: {{ default "8544" $.Values.geth.httprpc_port}} - targetPort: http-rpc - type: ClusterIP ---- -{{- end }} -{{- end }} diff --git a/charts/chainlink-cluster/templates/ingress.yaml b/charts/chainlink-cluster/templates/ingress.yaml deleted file mode 100644 index 9573ac54eb9..00000000000 --- a/charts/chainlink-cluster/templates/ingress.yaml +++ /dev/null @@ -1,43 +0,0 @@ -{{- if .Values.ingress.enabled -}} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: {{ $.Release.Name }} - labels: - app: {{ $.Release.Name }} - release: {{ $.Release.Name }} - {{- range $key, $value := $.Values.labels }} - {{ $key }}: {{ $value | quote }} - {{- end }} - annotations: - alb.ingress.kubernetes.io/backend-protocol: HTTP - alb.ingress.kubernetes.io/certificate-arn: {{ $.Values.ingress.annotation_certificate_arn | quote }} - alb.ingress.kubernetes.io/group.name: {{ $.Values.ingress.annotation_group_name | quote }} - alb.ingress.kubernetes.io/scheme: internal - alb.ingress.kubernetes.io/target-type: ip - external-dns.alpha.kubernetes.io/ttl: "120" - {{- if .Values.ingress.extra_annotations }} - {{- range $key, $value := .Values.ingress.extra_annotations }} - {{ $key }}: {{ $value | quote }} - {{- end }} - {{- end }} -spec: - {{- with .Values.ingress.ingressClassName }} - ingressClassName: {{ . }} - {{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ .host }} - http: - paths: - {{- range .http.paths }} - - path: "/*" - pathType: ImplementationSpecific - backend: - service: - name: {{ .backend.service.name }} - port: - number: {{ .backend.service.port.number }} - {{- end }} - {{- end }} -{{- end -}} diff --git a/charts/chainlink-cluster/templates/mockserver-networkpolicy.yaml b/charts/chainlink-cluster/templates/mockserver-networkpolicy.yaml deleted file mode 100644 index 0fa48dcfc41..00000000000 --- a/charts/chainlink-cluster/templates/mockserver-networkpolicy.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and .Values.mockserver.enabled .Values.networkPolicies.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ $.Release.Name }}-mockserver -spec: - podSelector: - matchLabels: - app: mockserver - policyTypes: - - Ingress - ingress: - - from: - # Allow http traffic from the node pods. - - podSelector: - matchLabels: - app: {{ $.Release.Name }} - ports: - - protocol: TCP - port: 1080 -{{- end }} diff --git a/charts/chainlink-cluster/templates/networkpolicy-default.yaml b/charts/chainlink-cluster/templates/networkpolicy-default.yaml deleted file mode 100644 index 10927c26eb6..00000000000 --- a/charts/chainlink-cluster/templates/networkpolicy-default.yaml +++ /dev/null @@ -1,43 +0,0 @@ -{{- if and .Values.mockserver.enabled .Values.networkPolicies.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: default -spec: - podSelector: - matchLabels: {} - policyTypes: - - Ingress - - Egress - ingress: - {{- if and .Values.networkPolicyDefault.ingress.allowCustomCidrs (not (empty .Values.networkPolicyDefault.ingress.customCidrs)) }} - # Using a comma separated list to make it easy to pass in with: - # `helm template ... --set networkPolicyDefault.ingress.customCidrs=...` - {{- $cidrs := splitList "," .Values.networkPolicyDefault.ingress.customCidrs }} - - from: - {{- range $cidr := $cidrs }} - - ipBlock: - cidr: {{ $cidr | quote }} - {{- end }} - {{- else }} - # Deny all ingress if no rules are specified. Rules can still be specified in other templates. - - {} - {{- end }} - egress: - - to: - - namespaceSelector: - matchLabels: - kubernetes.io/metadata.name: "{{ $.Release.Namespace }}" - - to: - - namespaceSelector: - matchLabels: - kubernetes.io/metadata.name: kube-system - podSelector: - matchLabels: - k8s-app: kube-dns - ports: - - protocol: TCP - port: 53 - - protocol: UDP - port: 53 -{{- end }} \ No newline at end of file diff --git a/charts/chainlink-cluster/templates/tests/test-connection.yaml b/charts/chainlink-cluster/templates/tests/test-connection.yaml deleted file mode 100644 index b03b6a570c7..00000000000 --- a/charts/chainlink-cluster/templates/tests/test-connection.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: cl-nodes-connection-test - annotations: - "helm.sh/hook": test -spec: - containers: - {{- range $cfg := .Values.chainlink.nodes }} - - name: curl-{{ $cfg.name }} - image: radial/busyboxplus:curl - command: ['curl'] - args: [ '{{ $.Release.Name }}-{{ $cfg.name }}:{{ $.Values.chainlink.web_port }}' ] - {{- end }} - restartPolicy: Never \ No newline at end of file diff --git a/charts/chainlink-cluster/values.yaml b/charts/chainlink-cluster/values.yaml deleted file mode 100644 index d6315f488fd..00000000000 --- a/charts/chainlink-cluster/values.yaml +++ /dev/null @@ -1,439 +0,0 @@ -# override resources for keys "chainlink", "db", or "geth" if needed -# resources: -# requests: -# cpu: 350m -# memory: 1024Mi -# limits: -# cpu: 350m -# memory: 1024Mi -# images can be overriden for the same keys: -# image: ethereum/client-go -# version: stable -chainlink: - enabled: true - global: - # `toml` is initially set to null. Uncomment and modify the following example as needed. - # Example configuration parameters for all Chainlink nodes. Can be overridden by individual node configurations and via `overridesToml`. - # toml: |- - # [Log] - # Level = 'info' - # [WebServer] - # HTTPPort = 6688 - toml: null - # `overridesToml` is initially set to null. Uncomment and modify the following example as needed. - # Example configuration parameters that override the main configuration. - # overridesToml: |- - # [Log] - # Level = 'debug' - # [WebServer] - # HTTPPort = 6690 - overridesToml: null - podSecurityContext: - fsGroup: 14933 - securityContext: - capabilities: - drop: - - ALL - readOnlyRootFilesystem: false - runAsNonRoot: true - runAsUser: 14933 - runAsGroup: 14933 - web_port: 6688 - p2p_port: 6690 - nodes: - - name: node-1 - image: "public.ecr.aws/chainlink/chainlink:latest" - # default resources are 300m/1Gi - # first node need more resources to build faster inside container - # at least 2Gi of memory is required otherwise build will fail (OOM) - resources: - requests: - cpu: 2000m - memory: 2048Mi - limits: - cpu: 2000m - memory: 2048Mi - # override default config per node - # for example, use OCRv2 P2P setup, the whole config - # toml: | - # RootDir = './clroot' - # [Log] - # JSONConsole = true - # Level = 'debug' - # [WebServer] - # AllowOrigins = '*' - # SecureCookies = false - # SessionTimeout = '999h0m0s' - # [OCR2] - # Enabled = true - # [P2P] - # [P2P.V2] - # Enabled = false - # AnnounceAddresses = [] - # DefaultBootstrappers = [] - # DeltaDial = '15s' - # DeltaReconcile = '1m0s' - # ListenAddresses = [] - # [[EVM]] - # ChainID = '1337' - # MinContractPayment = '0' - # [[EVM.Nodes]] - # Name = 'node-0' - # WSURL = 'ws://geth:8546' - # HTTPURL = 'http://geth:8544' - # [WebServer.TLS] - # HTTPSPort = 0 - # or use overridesToml to override some part of configuration - # overridesToml: | - - name: node-2 - - name: node-3 - - name: node-4 - - name: node-5 - - name: node-6 - -# each CL node have a dedicated PostgreSQL 11.15 -# use StatefulSet by setting: -# -# stateful: true -# capacity 10Gi -# -# if you are running long tests -db: - enabled: true - podSecurityContext: - fsGroup: 999 - securityContext: - capabilities: - drop: - - ALL - readOnlyRootFilesystem: false - runAsNonRoot: true - runAsUser: 999 - runAsGroup: 999 - stateful: false - image: "postgres:15.6" - resources: - requests: - cpu: 1 - memory: 1024Mi - limits: - cpu: 1 - memory: 1024Mi -# default cluster shipped with latest Geth ( dev mode by default ) -geth: - enabled: true - podSecurityContext: - fsGroup: 999 - securityContext: - capabilities: - drop: - - ALL - readOnlyRootFilesystem: false - runAsNonRoot: true - runAsUser: 999 - runAsGroup: 999 - version: v1.12.0 - wsRpcPort: 8546 - httpRpcPort: 8544 - blocktime: 1 - chains: - - networkId: 1337 - # use to inject custom configuration for each chain, e.g. GasEstimator - # - customEVMConfigToml: | - # [EVM.GasEstimator] - # PriceMax = '200 gwei' - # LimitDefault = 6000000 - # FeeCapDefault = '200 gwei' - # [EVM.GasEstimator.BlockHistory] - # BlockHistorySize = 200 - # EIP1559FeeCapBufferBlocks = 0 - - networkId: 2337 - resources: - requests: - cpu: 1 - memory: 1024Mi - limits: - cpu: 1 - memory: 1024Mi -# mockserver is https://www.mock-server.com/where/kubernetes.html -# used to stub External Adapters -mockserver: - enabled: true - releasenameOverride: mockserver - service: - type: ClusterIP - app: - runAsUser: 999 - readOnlyRootFilesystem: false - port: 1080 - resources: - requests: - cpu: 1 - memory: 1024Mi - limits: - cpu: 1 - memory: 1024Mi -opentelemetry-collector: - enabled: true - mode: deployment - image: - repository: otel/opentelemetry-collector - tag: 0.95.0 - command: - name: otelcol - extraVolumes: - - name: trace-data - emptyDir: {} - extraVolumeMounts: - - name: trace-data - mountPath: /tracing - podSecurityContext: - fsGroup: 10001 - securityContext: - runAsNonRoot: true - runAsUser: 10001 - runAsGroup: 10001 - config: - receivers: - otlp: - protocols: - grpc: - endpoint: ${env:MY_POD_IP}:4317 - http: - endpoint: ${env:MY_POD_IP}:4318 - exporters: - otlp: - endpoint: app-tempo:4317 - tls: - insecure: true - service: - telemetry: - logs: - level: "debug" - pipelines: - traces: - receivers: [otlp] - exporters: [otlp] - -tempo: - enabled: true - image: - tag: "1.7.2" - # default storage path: /var/tempo/ - securityContext: - runAsNonRoot: true - runAsUser: 10001 - runAsGroup: 10001 - tempo: - storage: - trace: - backend: local # backend configuration to use - wal: - path: /tmp/tempo/wal # where to store the wal locally - local: - path: /tmp/tempo/blocks - -grafana: - enabled: true - image: - tag: 10.4.1 - rbac: - namespaced: true - datasources: - datasources.yaml: - apiVersion: 1 - datasources: - - name: Tempo - type: tempo - access: proxy - orgId: 1 - url: http://app-tempo:3100 - basicAuth: false - isDefault: true - version: 1 - editable: false - uid: tempo - jsonData: - httpMethod: GET - serviceMap: - datasourceUid: prometheus - env: - GF_AUTH_ANONYMOUS_ENABLED: "true" - GF_AUTH_ANONYMOUS_ORG_ROLE: "Admin" - GF_AUTH_DISABLE_LOGIN_FORM: "true" - GF_FEATURE_TOGGLES_ENABLE: "traceqlEditor tempoSearch tempoServiceGraph" - -ingress: - enabled: false - annotations: {} - ingressClassName: alb - hosts: - - host: chainlink-node-1.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: chainlink-node-1 - port: - number: 6688 - - host: chainlink-node-2.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: chainlink-node-2 - port: - number: 6688 - - host: chainlink-node-3.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: chainlink-node-3 - port: - number: 6688 - - host: chainlink-node-4.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: chainlink-node-4 - port: - number: 6688 - - host: chainlink-node-5.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: chainlink-node-5 - port: - number: 6688 - - host: chainlink-node-6.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: chainlink-node-6 - port: - number: 6688 - - host: chainlink-geth-http.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: geth - port: - number: 8544 - - host: chainlink-geth-ws.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: geth - port: - number: 8546 - - host: chainlink-mockserver.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: mockserver - port: - number: 1080 - - host: chainlink-grafana.local - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: grafana - port: - number: 80 -# monitoring.coreos.com/v1 PodMonitor for each node -prometheusMonitor: true - -# deployment placement, standard helm stuff -podAnnotations: -nodeSelector: -tolerations: -affinity: - -networkPolicies: - enabled: true - customPolicies: - grafanaToTempoEgress: - podSelector: - matchLabels: - app: grafana - egress: - - to: - - podSelector: - matchLabels: - app: tempo - ports: - - protocol: TCP - port: 3100 - tempoIngressFromGrafana: - podSelector: - matchLabels: - app: tempo - ingress: - - from: - - podSelector: - matchLabels: - app: grafana - ports: - - protocol: TCP - port: 3100 - chainlinkToOtelCollectorEgress: - podSelector: - matchLabels: - app: chainlink - egress: - - to: - - podSelector: - matchLabels: - app: otel-collector - ports: - - protocol: TCP - port: 4317 - otelCollectorToTempoEgress: - podSelector: - matchLabels: - app: otel-collector - egress: - - to: - - podSelector: - matchLabels: - app: tempo - ports: - - protocol: TCP - port: 4317 - -# Configure the default network policy. -networkPolicyDefault: - ingress: - allowCustomCidrs: false - # String of comma separated CIDRs - customCidrs: null - # Example: - # customCidrs: "10.0.0.0/16,192.168.0.1/24" diff --git a/crib/.env.example b/crib/.env.example index 703c7bf7f83..e35d0d3e580 100644 --- a/crib/.env.example +++ b/crib/.env.example @@ -13,5 +13,9 @@ DEVSPACE_INGRESS_CERT_ARN= # Time to wait for pods to be in `Ready` condition DEVSPACE_K8S_POD_WAIT_TIMEOUT=600s +# HELM repo URI for the crib-chainlink-cluster helm chart +CHAINLINK_CLUSTER_HELM_CHART_URI= + # The duration that the namespace and all of its associated resources will be kept alive. NS_TTL=72h + diff --git a/crib/devspace.yaml b/crib/devspace.yaml index 9c2895e9ac6..213fe4c24c7 100644 --- a/crib/devspace.yaml +++ b/crib/devspace.yaml @@ -99,8 +99,8 @@ deployments: helm: releaseName: "app" chart: - name: cl-cluster - path: ../charts/chainlink-cluster + name: ${CHAINLINK_CLUSTER_HELM_CHART_URI} + version: 0.5.0 # for simplicity, we define all the values here # they can be defined the same way in values.yml # devspace merges these "values" with the "values.yaml" before deploy diff --git a/crib/scripts/check_env_vars.sh b/crib/scripts/check_env_vars.sh index f26f78e7470..55480313800 100755 --- a/crib/scripts/check_env_vars.sh +++ b/crib/scripts/check_env_vars.sh @@ -7,6 +7,7 @@ required_vars=( "DEVSPACE_INGRESS_BASE_DOMAIN" "DEVSPACE_INGRESS_CERT_ARN" "DEVSPACE_K8S_POD_WAIT_TIMEOUT" + "CHAINLINK_CLUSTER_HELM_CHART_URI" "NS_TTL" ) diff --git a/crib/setup.sh b/crib/setup.sh index 536bef57c75..8e254909655 100755 --- a/crib/setup.sh +++ b/crib/setup.sh @@ -1,6 +1,20 @@ #!/usr/bin/env bash -set -e +set -euo pipefail + +# Function to extract the host URI of the ECR registry from OCI URI +extract_ecr_host_uri() { + local ecr_uri="$1" + # Regex to capture the ECR host URI + if [[ $ecr_uri =~ oci:\/\/([0-9]+\.dkr\.ecr\.[a-zA-Z0-9-]+\.amazonaws\.com) ]]; then + echo "${BASH_REMATCH[1]}" + else + echo "No valid ECR host URI found in the URI." + echo "Have you set CHAINLINK_CLUSTER_HELM_CHART_URI env var?" + exit 1 + fi +} + user_home="$HOME" file_path="$user_home/.aws/config" image="" @@ -33,5 +47,12 @@ else echo "Docker daemon is not running, exiting" exit 1 fi -aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin ${registry_id}.dkr.ecr.us-west-2.amazonaws.com -devspace use namespace $1 + +# Login to docker ECR registry +aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin "${registry_id}".dkr.ecr.us-west-2.amazonaws.com + +# Login to helm ECR registry +helm_registry_uri=$(extract_ecr_host_uri "${CHAINLINK_CLUSTER_HELM_CHART_URI}") +aws ecr get-login-password --region us-west-2 | helm registry login "$helm_registry_uri" --username AWS --password-stdin + +devspace use namespace "$1" diff --git a/charts/chainlink-cluster/values-profiles/README.md b/crib/values-profiles/README.md similarity index 100% rename from charts/chainlink-cluster/values-profiles/README.md rename to crib/values-profiles/README.md diff --git a/charts/chainlink-cluster/values-profiles/values-dev.yaml.example b/crib/values-profiles/values-dev.yaml.example similarity index 100% rename from charts/chainlink-cluster/values-profiles/values-dev.yaml.example rename to crib/values-profiles/values-dev.yaml.example diff --git a/lintconf.yaml b/lintconf.yaml deleted file mode 100644 index ff37371d476..00000000000 --- a/lintconf.yaml +++ /dev/null @@ -1,46 +0,0 @@ ---- -# Copied from: -# https://redhat-cop.github.io/ci/linting-testing-helm-charts.html -# with `min-spaces-from-content` changed to be compatible with prettier. -rules: - braces: - min-spaces-inside: 0 - max-spaces-inside: 0 - min-spaces-inside-empty: -1 - max-spaces-inside-empty: -1 - brackets: - min-spaces-inside: 0 - max-spaces-inside: 0 - min-spaces-inside-empty: -1 - max-spaces-inside-empty: -1 - colons: - max-spaces-before: 0 - max-spaces-after: 1 - commas: - max-spaces-before: 0 - min-spaces-after: 1 - max-spaces-after: 1 - comments: - require-starting-space: true - min-spaces-from-content: 1 - document-end: disable - document-start: disable # No --- to start a file - empty-lines: - max: 2 - max-start: 0 - max-end: 0 - hyphens: - max-spaces-after: 1 - indentation: - spaces: consistent - indent-sequences: whatever # - list indentation will handle both indentation and without - check-multi-line-strings: false - key-duplicates: enable - line-length: disable # Lines can be any length - new-line-at-end-of-file: disable - new-lines: - type: unix - trailing-spaces: enable - truthy: - level: warning - From 7b09076a101b47b731fa1b0ee9ce61f4a98254ab Mon Sep 17 00:00:00 2001 From: Anirudh Warrier <12178754+anirudhwarrier@users.noreply.github.com> Date: Thu, 25 Apr 2024 15:35:52 +0530 Subject: [PATCH 11/34] stream automation tests logs to grafana (AUTO-10273) (#12953) * stream nightly tests logs to loki * stream ondemand tests logs to loki --- .../action.yml | 49 +++++++++++++++++++ .../workflows/automation-nightly-tests.yml | 8 +++ .../workflows/automation-ondemand-tests.yml | 34 ++++++++++++- 3 files changed, 90 insertions(+), 1 deletion(-) diff --git a/.github/actions/setup-create-base64-upgrade-config/action.yml b/.github/actions/setup-create-base64-upgrade-config/action.yml index daa2d400262..ed25fd6375f 100644 --- a/.github/actions/setup-create-base64-upgrade-config/action.yml +++ b/.github/actions/setup-create-base64-upgrade-config/action.yml @@ -17,6 +17,23 @@ inputs: default: "public.ecr.aws/chainlink/chainlink" upgradeVersion: description: The git commit sha to use for the image tag + runId: + description: The run id + testLogCollect: + description: Whether to always collect logs, even for passing tests + default: "false" + lokiEndpoint: + description: Loki push endpoint + lokiTenantId: + description: Loki tenant id + lokiBasicAuth: + description: Loki basic auth + logstreamLogTargets: + description: Where to send logs (e.g. file, loki) + grafanaUrl: + description: Grafana URL + grafanaDashboardUrl: + description: Grafana dashboard URL runs: using: composite @@ -31,6 +48,14 @@ runs: CHAINLINK_POSTGRES_VERSION: ${{ inputs.chainlinkPostgresVersion }} UPGRADE_IMAGE: ${{ inputs.upgradeImage }} UPGRADE_VERSION: ${{ inputs.upgradeVersion }} + RUN_ID: ${{ inputs.runId }} + TEST_LOG_COLLECT: ${{ inputs.testLogCollect }} + LOKI_ENDPOINT: ${{ inputs.lokiEndpoint }} + LOKI_TENANT_ID: ${{ inputs.lokiTenantId }} + LOKI_BASIC_AUTH: ${{ inputs.lokiBasicAuth }} + LOGSTREAM_LOG_TARGETS: ${{ inputs.logstreamLogTargets }} + GRAFANA_URL: ${{ inputs.grafanaUrl }} + GRAFANA_DASHBOARD_URL: ${{ inputs.grafanaDashboardUrl }} run: | function convert_to_toml_array() { local IFS=',' @@ -47,6 +72,14 @@ runs: selected_networks=$(convert_to_toml_array "$SELECTED_NETWORKS") + if [ -n "$TEST_LOG_COLLECT" ]; then + test_log_collect=true + else + test_log_collect=false + fi + + log_targets=$(convert_to_toml_array "$LOGSTREAM_LOG_TARGETS") + cat << EOF > config.toml [Network] selected_networks=$selected_networks @@ -59,6 +92,22 @@ runs: [ChainlinkUpgradeImage] image="$UPGRADE_IMAGE" version="$UPGRADE_VERSION" + + [Logging] + test_log_collect=$test_log_collect + run_id="$RUN_ID" + + [Logging.LogStream] + log_targets=$log_targets + + [Logging.Loki] + tenant_id="$LOKI_TENANT_ID" + endpoint="$LOKI_ENDPOINT" + basic_auth_secret="$LOKI_BASIC_AUTH" + + [Logging.Grafana] + base_url="$GRAFANA_URL" + dashboard_url="$GRAFANA_DASHBOARD_URL" EOF BASE64_CONFIG_OVERRIDE=$(cat config.toml | base64 -w 0) diff --git a/.github/workflows/automation-nightly-tests.yml b/.github/workflows/automation-nightly-tests.yml index c3b874548ac..b44a7f56e65 100644 --- a/.github/workflows/automation-nightly-tests.yml +++ b/.github/workflows/automation-nightly-tests.yml @@ -95,6 +95,14 @@ jobs: chainlinkVersion: "latest" upgradeImage: ${{ env.CHAINLINK_IMAGE }} upgradeVersion: ${{ github.sha }} + runId: ${{ github.run_id }} + testLogCollect: "true" + lokiEndpoint: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push + lokiTenantId: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + lokiBasicAuth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: ${{ vars.GRAFANA_URL }} + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@5dd916d08c03cb5f9a97304f4f174820421bb946 # v2.3.11 env: diff --git a/.github/workflows/automation-ondemand-tests.yml b/.github/workflows/automation-ondemand-tests.yml index 167dccf3bbf..dade0f331b9 100644 --- a/.github/workflows/automation-ondemand-tests.yml +++ b/.github/workflows/automation-ondemand-tests.yml @@ -226,7 +226,15 @@ jobs: UPGRADE_IMAGE: ${{ steps.determine-build.outputs.upgrade_image }} PYROSCOPE_SERVER: ${{ matrix.tests.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 PYROSCOPE_ENVIRONMENT: ${{ matrix.tests.pyroscope_env }} - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} + PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} + RUN_ID: ${{ github.run_id }} + TEST_LOG_COLLECT: "true" + LOKI_ENDPOINT: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push + LOKI_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + LOKI_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + LOGSTREAM_LOG_TARGETS: ${{ vars.LOGSTREAM_LOG_TARGETS }} + GRAFANA_URL: ${{ vars.GRAFANA_URL }} + GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" run: | echo ::add-mask::$UPGRADE_IMAGE echo ::add-mask::$OLD_IMAGE @@ -242,6 +250,14 @@ jobs: pyroscope_enabled=false fi + if [ -n "$TEST_LOG_COLLECT" ]; then + test_log_collect=true + else + test_log_collect=false + fi + + log_targets=$(convert_to_toml_array "$LOGSTREAM_LOG_TARGETS") + cat << EOF > config.toml [Network] selected_networks=$selected_networks @@ -254,6 +270,22 @@ jobs: image="$UPGRADE_IMAGE" version="$UPGRADE_VERSION" + [Logging] + test_log_collect=$test_log_collect + run_id="$RUN_ID" + + [Logging.LogStream] + log_targets=$log_targets + + [Logging.Loki] + tenant_id="$LOKI_TENANT_ID" + endpoint="$LOKI_ENDPOINT" + basic_auth_secret="$LOKI_BASIC_AUTH" + + [Logging.Grafana] + base_url="$GRAFANA_URL" + dashboard_url="$GRAFANA_DASHBOARD_URL" + [Pyroscope] enabled=$pyroscope_enabled server_url="$PYROSCOPE_SERVER" From c91052c9d6faa70f01e3ac695cfd6eacd541b88e Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Thu, 25 Apr 2024 06:24:11 -0400 Subject: [PATCH 12/34] Create new CRIB setup script (#12956) * Add CRIB scripts to nix $PATH * Create new CRIB setup script * Update CRIB README * Clarify comment * Fix typo --------- Co-authored-by: Radek Scheibinger --- crib/.env.example | 6 ++ crib/README.md | 15 ++-- crib/scripts/cribbit.sh | 179 ++++++++++++++++++++++++++++++++++++++++ crib/setup.sh | 58 ------------- shell.nix | 6 ++ 5 files changed, 199 insertions(+), 65 deletions(-) create mode 100755 crib/scripts/cribbit.sh delete mode 100755 crib/setup.sh diff --git a/crib/.env.example b/crib/.env.example index e35d0d3e580..e24473a9a22 100644 --- a/crib/.env.example +++ b/crib/.env.example @@ -19,3 +19,9 @@ CHAINLINK_CLUSTER_HELM_CHART_URI= # The duration that the namespace and all of its associated resources will be kept alive. NS_TTL=72h +## +# These are used by the shell script: cribbit.sh +## +AWS_REGION= +AWS_SSO_ROLE_NAME= +AWS_SSO_START_URL= diff --git a/crib/README.md b/crib/README.md index c9106d401cd..a88eedb5c41 100644 --- a/crib/README.md +++ b/crib/README.md @@ -26,16 +26,17 @@ Configure the cluster, see `deployments.app.helm.values` and [values.yaml](../ch Set up your K8s access -``` -export DEVSPACE_IMAGE="..." -./setup.sh ${my-personal-namespace-name-crib} -``` +Copy the `.env.example` file to `.env` and fill in the required values -Create a .env file based on the .env.sample file +```sh +cp crib/.env.example crib/.env +``` ```sh -cp .env.sample .env -# Fill in the required values in .env +cd crib/ +nix develop +# Pro tip: use `crib-` as a prefix for your namespace. +cribbit.sh ``` Build and deploy the current state of your repository diff --git a/crib/scripts/cribbit.sh b/crib/scripts/cribbit.sh new file mode 100755 index 00000000000..316791b10cb --- /dev/null +++ b/crib/scripts/cribbit.sh @@ -0,0 +1,179 @@ +#!/usr/bin/env bash + +set -euo pipefail + +############################# +# __________ +# < CRIBbit! > +# ---------- +# _ _ / +# (o)--(o) / +# /.______.\ +# \________/ +# ./ \. +# ( . , ) +# \ \_\\//_/ / +# ~~ ~~ ~~ +# +# Initialize your CRIB +# environment. +############################# + +DEVSPACE_NAMESPACE="${1:-}" +if [[ -z "${DEVSPACE_NAMESPACE}" ]]; then + echo "Usage: $0 " + exit 1 +fi + +# Bail if $DEVSPACE_NAMESPACE does not begin with a crib- prefix or does not have an override set. +if [[ ! "${DEVSPACE_NAMESPACE}" =~ ^crib- ]] && [[ -z "${CRIB_IGNORE_NAMESPACE_PREFIX:-}" ]]; then + echo "Error: DEVSPACE_NAMESPACE must begin with 'crib-' prefix." + exit 1 +fi + +# Path to the .env file +repo_root=$(git rev-parse --show-toplevel 2>/dev/null || echo ".") +env_file="${repo_root}/crib/.env" + +# Source .env file if it exists +if [[ -f "${env_file}" ]]; then + # shellcheck disable=SC1090 + source "${env_file}" +else + echo "Error: .env file not found at $env_file" + exit 1 +fi + +# List of required environment variables +required_vars=( + "AWS_REGION" + # Should be the short name and not the full IAM role ARN. + "AWS_SSO_ROLE_NAME" + # The AWS SSO start URL, e.g. https://.awsapps.com/start + "AWS_SSO_START_URL" + "DEVSPACE_IMAGE" + "HOME" +) + +missing_vars=0 # Counter for missing variables + +for var in "${required_vars[@]}"; do + if [[ -z "${!var:-}" ]]; then # If variable is unset or empty + echo "Error: Environment variable ${var} is not set." + missing_vars=$((missing_vars + 1)) + fi +done + +# Exit with an error if any variables were missing +if [[ $missing_vars -ne 0 ]]; then + echo "Error: Total missing environment variables: $missing_vars" + exit 1 +fi + +## +# Setup AWS Profile +## + +path_aws_config="$HOME/.aws/config" +aws_account_id_ecr_registry=$(echo "${DEVSPACE_IMAGE}" | cut -d'.' -f1) +aws_profile_name="staging-crib" + +if grep -q "$aws_profile_name" "$path_aws_config"; then + echo "Info: Skip updating ${path_aws_config}. Profile already set: ${aws_profile_name}" +else + cat <> "$path_aws_config" +[profile $aws_profile_name] +region=${AWS_REGION} +sso_start_url=${AWS_SSO_START_URL} +sso_region=${AWS_REGION} +sso_account_id=${aws_account_id_ecr_registry} +sso_role_name=${AWS_SSO_ROLE_NAME} +EOF + echo "Info: ${path_aws_config} modified. Added profile: ${aws_profile_name}" +fi + +echo "Info: Setting AWS Profile env var: AWS_PROFILE=${aws_profile_name}" +export AWS_PROFILE=${aws_profile_name} + +if aws sts get-caller-identity > /dev/null 2>&1; then + echo "Info: AWS credentials working." +else + echo "Info: AWS credentials not detected. Attempting to login through SSO." + aws sso login +fi + +# Check again and fail this time if not successful +if ! aws sts get-caller-identity > /dev/null 2>&1; then + echo "Error: AWS credentials still not detected. Exiting." + exit 1 +fi + +## +# Setup EKS KUBECONFIG +## + +path_kubeconfig="${KUBECONFIG:-$HOME/.kube/config}" +eks_cluster_name="${CRIB_EKS_CLUSTER_NAME:-main-stage-cluster}" +eks_alias_name="${CRIB_EKS_ALIAS_NAME:-main-stage-cluster-crib}" + +if [[ ! -f "${path_kubeconfig}" ]] || ! grep -q "name: ${eks_alias_name}" "${path_kubeconfig}"; then + echo "Info: KUBECONFIG file (${path_kubeconfig}) not found or alias (${eks_alias_name}) not found. Attempting to update kubeconfig." + aws eks update-kubeconfig \ + --name "${eks_cluster_name}" \ + --alias "${eks_alias_name}" \ + --region "${AWS_REGION}" +else + echo "Info: Alias '${eks_alias_name}' already exists in kubeconfig. No update needed." + echo "Info: Setting kubernetes context to: ${eks_alias_name}" + kubectl config use-context "${eks_alias_name}" +fi + +## +# Check Docker Daemon +## + +if docker info > /dev/null 2>&1; then + echo "Info: Docker daemon is running, authorizing registry" +else + echo "Error: Docker daemon is not running. Exiting." + exit 1 +fi + +## +# AWS ECR Login +## + +# Function to extract the host URI of the ECR registry from OCI URI +extract_ecr_host_uri() { + local ecr_uri="$1" + # Regex to capture the ECR host URI + if [[ $ecr_uri =~ oci:\/\/([0-9]+\.dkr\.ecr\.[a-zA-Z0-9-]+\.amazonaws\.com) ]]; then + echo "${BASH_REMATCH[1]}" + else + echo "No valid ECR host URI found in the URI." + echo "Have you set CHAINLINK_CLUSTER_HELM_CHART_URI env var?" + exit 1 + fi +} + +# Set env var CRIB_SKIP_ECR_LOGIN=true to skip ECR login. +if [[ -n "${CRIB_SKIP_ECR_LOGIN:-}" ]]; then + echo "Info: Skipping ECR login." +else + echo "Info: Logging docker into AWS ECR registry." + aws ecr get-login-password \ + --region "${AWS_REGION}" \ + | docker login --username AWS \ + --password-stdin "${aws_account_id_ecr_registry}.dkr.ecr.${AWS_REGION}.amazonaws.com" + + echo "Info: Logging helm into AWS ECR registry." + helm_registry_uri=$(extract_ecr_host_uri "${CHAINLINK_CLUSTER_HELM_CHART_URI}") + aws ecr get-login-password --region "${AWS_REGION}" \ + | helm registry login "$helm_registry_uri" --username AWS --password-stdin +fi + +## +# Setup DevSpace +## + +devspace use namespace "${DEVSPACE_NAMESPACE}" diff --git a/crib/setup.sh b/crib/setup.sh deleted file mode 100755 index 8e254909655..00000000000 --- a/crib/setup.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# Function to extract the host URI of the ECR registry from OCI URI -extract_ecr_host_uri() { - local ecr_uri="$1" - # Regex to capture the ECR host URI - if [[ $ecr_uri =~ oci:\/\/([0-9]+\.dkr\.ecr\.[a-zA-Z0-9-]+\.amazonaws\.com) ]]; then - echo "${BASH_REMATCH[1]}" - else - echo "No valid ECR host URI found in the URI." - echo "Have you set CHAINLINK_CLUSTER_HELM_CHART_URI env var?" - exit 1 - fi -} - -user_home="$HOME" -file_path="$user_home/.aws/config" -image="" -registry_id=$(echo "$DEVSPACE_IMAGE" | cut -d'.' -f1) - -if grep -q "staging-crib" "$file_path"; then - echo "Staging AWS config is already applied, role is 'staging-crib'" -else - cat <> "$file_path" -[profile staging-crib] -region=us-west-2 -sso_start_url=https://smartcontract.awsapps.com/start -sso_region=us-west-2 -sso_account_id=${registry_id} -sso_role_name=CRIB-ECR-Power -EOF - echo "~/.aws/config modified, added 'staging-crib" -fi - -# Login through SSO -aws sso login --profile staging-crib -# Update kubeconfig and switch context -export AWS_PROFILE=staging-crib -aws eks update-kubeconfig --name main-stage-cluster --alias main-stage-cluster-crib --profile staging-crib - -# Check if the Docker daemon is running -if docker info > /dev/null 2>&1; then - echo "Docker daemon is running, authorizing registry" -else - echo "Docker daemon is not running, exiting" - exit 1 -fi - -# Login to docker ECR registry -aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin "${registry_id}".dkr.ecr.us-west-2.amazonaws.com - -# Login to helm ECR registry -helm_registry_uri=$(extract_ecr_host_uri "${CHAINLINK_CLUSTER_HELM_CHART_URI}") -aws ecr get-login-password --region us-west-2 | helm registry login "$helm_registry_uri" --username AWS --password-stdin - -devspace use namespace "$1" diff --git a/shell.nix b/shell.nix index 69bf202351d..1fde34fcfd8 100644 --- a/shell.nix +++ b/shell.nix @@ -57,4 +57,10 @@ mkShell' { PGDATA = "db"; CL_DATABASE_URL = "postgresql://chainlink:chainlink@localhost:5432/chainlink_test?sslmode=disable"; + + shellHook = '' + # Find the root of the git repository + repo_root=$(git rev-parse --show-toplevel 2>/dev/null || echo ".") + export PATH=$PATH:$repo_root/crib/scripts + ''; } From ac7d3409ed9bc98af970ca75c3b92e41e4fb01cf Mon Sep 17 00:00:00 2001 From: george-dorin <120329946+george-dorin@users.noreply.github.com> Date: Thu, 25 Apr 2024 17:30:02 +0300 Subject: [PATCH 13/34] Enable jpfc cache by default (#12966) * Draft * Check JuelsPerFeeCoinCache before checking Disable param * Add test * Update NewInMemoryDataSourceCache * Update NewInMemoryDataSourceCache --- .changeset/warm-impalas-return.md | 5 +++ .../ocr2/plugins/median/config/config.go | 1 + core/services/ocr2/plugins/median/services.go | 5 +-- core/services/ocr2/validate/validate_test.go | 41 +++++++++++++++++++ core/services/ocrcommon/data_source.go | 17 +++++--- core/services/ocrcommon/data_source_test.go | 6 +-- 6 files changed, 63 insertions(+), 12 deletions(-) create mode 100644 .changeset/warm-impalas-return.md diff --git a/.changeset/warm-impalas-return.md b/.changeset/warm-impalas-return.md new file mode 100644 index 00000000000..167d831692c --- /dev/null +++ b/.changeset/warm-impalas-return.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#added JuelsPerFeeCoinCache is enabled by default for OCR2 jobs, added `Disable` field under [pluginConfig.JuelsPerFeeCoinCache] tag to disable this feature (e.g. Disable=true) diff --git a/core/services/ocr2/plugins/median/config/config.go b/core/services/ocr2/plugins/median/config/config.go index 9cfda641552..310662ef6c0 100644 --- a/core/services/ocr2/plugins/median/config/config.go +++ b/core/services/ocr2/plugins/median/config/config.go @@ -20,6 +20,7 @@ type PluginConfig struct { } type JuelsPerFeeCoinCache struct { + Disable bool `json:"disable"` UpdateInterval models.Interval `json:"updateInterval"` StalenessAlertThreshold models.Interval `json:"stalenessAlertThreshold"` } diff --git a/core/services/ocr2/plugins/median/services.go b/core/services/ocr2/plugins/median/services.go index 779ea4f346c..e2b8da13407 100644 --- a/core/services/ocr2/plugins/median/services.go +++ b/core/services/ocr2/plugins/median/services.go @@ -12,7 +12,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-feeds/median" - "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services" @@ -127,9 +126,9 @@ func NewMedianServices(ctx context.Context, CreatedAt: time.Now(), }, lggr) - if pluginConfig.JuelsPerFeeCoinCache != nil { + if pluginConfig.JuelsPerFeeCoinCache == nil || (pluginConfig.JuelsPerFeeCoinCache != nil && !pluginConfig.JuelsPerFeeCoinCache.Disable) { lggr.Infof("juelsPerFeeCoin data source caching is enabled") - juelsPerFeeCoinSourceCache, err2 := ocrcommon.NewInMemoryDataSourceCache(juelsPerFeeCoinSource, kvStore, *pluginConfig.JuelsPerFeeCoinCache) + juelsPerFeeCoinSourceCache, err2 := ocrcommon.NewInMemoryDataSourceCache(juelsPerFeeCoinSource, kvStore, pluginConfig.JuelsPerFeeCoinCache) if err2 != nil { return nil, err2 } diff --git a/core/services/ocr2/validate/validate_test.go b/core/services/ocr2/validate/validate_test.go index 305a727d030..fad5a36e51f 100644 --- a/core/services/ocr2/validate/validate_test.go +++ b/core/services/ocr2/validate/validate_test.go @@ -693,6 +693,47 @@ Command="some random command" require.Error(t, err) require.ErrorContains(t, err, "failed to find binary") }, + }, { + name: "minimal OCR2 oracle spec with JuelsPerFeeCoinCache", + toml: ` +type = "offchainreporting2" +pluginType = "median" +schemaVersion = 1 +relay = "evm" +contractID = "0x613a38AC1659769640aaE063C651F48E0250454C" +observationSource = """ +ds1 [type=bridge name=voter_turnout]; +ds1_parse [type=jsonparse path="one,two"]; +ds1_multiply [type=multiply times=1.23]; +ds1 -> ds1_parse -> ds1_multiply -> answer1; +answer1 [type=median index=0]; +""" +[relayConfig] +chainID = 1337 +[pluginConfig] +juelsPerFeeCoinSource = """ +ds1 [type=bridge name=voter_turnout]; +ds1_parse [type=jsonparse path="one,two"]; +ds1_multiply [type=multiply times=1.23]; +ds1 -> ds1_parse -> ds1_multiply -> answer1; +answer1 [type=median index=0]; +""" +[pluginConfig.JuelsPerFeeCoinCache] +Disable=false +UpdateInterval="1m" +`, + assertion: func(t *testing.T, os job.Job, err error) { + require.NoError(t, err) + b, err := jsonapi.Marshal(os.OCR2OracleSpec) + require.NoError(t, err) + var r job.OCR2OracleSpec + err = jsonapi.Unmarshal(b, &r) + require.NoError(t, err) + assert.Equal(t, "median", string(r.PluginType)) + var pc medianconfig.PluginConfig + require.NoError(t, json.Unmarshal(r.PluginConfig.Bytes(), &pc)) + require.NoError(t, medianconfig.ValidatePluginConfig(pc)) + }, }, } diff --git a/core/services/ocrcommon/data_source.go b/core/services/ocrcommon/data_source.go index 9ca111dea68..cb544e01639 100644 --- a/core/services/ocrcommon/data_source.go +++ b/core/services/ocrcommon/data_source.go @@ -113,18 +113,23 @@ type DataSourceCacheService interface { median.DataSource } -func NewInMemoryDataSourceCache(ds median.DataSource, kvStore job.KVStore, cacheCfg config.JuelsPerFeeCoinCache) (DataSourceCacheService, error) { +func NewInMemoryDataSourceCache(ds median.DataSource, kvStore job.KVStore, cacheCfg *config.JuelsPerFeeCoinCache) (DataSourceCacheService, error) { inMemoryDS, ok := ds.(*inMemoryDataSource) if !ok { return nil, errors.Errorf("unsupported data source type: %T, only inMemoryDataSource supported", ds) } - - updateInterval, stalenessAlertThreshold := cacheCfg.UpdateInterval.Duration(), cacheCfg.StalenessAlertThreshold.Duration() - if updateInterval == 0 { + var updateInterval, stalenessAlertThreshold time.Duration + if cacheCfg == nil { updateInterval = defaultUpdateInterval - } - if stalenessAlertThreshold == 0 { stalenessAlertThreshold = defaultStalenessAlertThreshold + } else { + updateInterval, stalenessAlertThreshold = cacheCfg.UpdateInterval.Duration(), cacheCfg.StalenessAlertThreshold.Duration() + if updateInterval == 0 { + updateInterval = defaultUpdateInterval + } + if stalenessAlertThreshold == 0 { + stalenessAlertThreshold = defaultStalenessAlertThreshold + } } dsCache := &inMemoryDataSourceCache{ diff --git a/core/services/ocrcommon/data_source_test.go b/core/services/ocrcommon/data_source_test.go index 05ba0f4aa42..a62852eaced 100644 --- a/core/services/ocrcommon/data_source_test.go +++ b/core/services/ocrcommon/data_source_test.go @@ -80,7 +80,7 @@ func Test_CachedInMemoryDataSourceErrHandling(t *testing.T) { mockKVStore := mocks.KVStore{} mockKVStore.On("Store", mock.Anything, mock.Anything, mock.Anything).Return(nil) mockKVStore.On("Get", mock.Anything, mock.Anything).Return(nil, nil) - dsCache, err := ocrcommon.NewInMemoryDataSourceCache(ds, &mockKVStore, config.JuelsPerFeeCoinCache{UpdateInterval: models.Interval(time.Second * 2)}) + dsCache, err := ocrcommon.NewInMemoryDataSourceCache(ds, &mockKVStore, &config.JuelsPerFeeCoinCache{UpdateInterval: models.Interval(time.Second * 2)}) require.NoError(t, err) servicetest.Run(t, dsCache) @@ -114,7 +114,7 @@ func Test_CachedInMemoryDataSourceErrHandling(t *testing.T) { mockKVStore.On("Get", mock.Anything, mock.Anything).Return(result, nil) // set updater to a long time so that it doesn't log errors after the test is done - dsCache, err := ocrcommon.NewInMemoryDataSourceCache(ds, &mockKVStore, config.JuelsPerFeeCoinCache{UpdateInterval: models.Interval(time.Hour * 100)}) + dsCache, err := ocrcommon.NewInMemoryDataSourceCache(ds, &mockKVStore, &config.JuelsPerFeeCoinCache{UpdateInterval: models.Interval(time.Hour * 100)}) require.NoError(t, err) changeResultValue(runner, "-1", true, false) servicetest.Run(t, dsCache) @@ -133,7 +133,7 @@ func Test_CachedInMemoryDataSourceErrHandling(t *testing.T) { mockKVStore.On("Get", mock.Anything, mock.Anything).Return(nil, assert.AnError) // set updater to a long time so that it doesn't log errors after the test is done - dsCache, err := ocrcommon.NewInMemoryDataSourceCache(ds, &mockKVStore, config.JuelsPerFeeCoinCache{UpdateInterval: models.Interval(time.Hour * 100)}) + dsCache, err := ocrcommon.NewInMemoryDataSourceCache(ds, &mockKVStore, &config.JuelsPerFeeCoinCache{UpdateInterval: models.Interval(time.Hour * 100)}) require.NoError(t, err) changeResultValue(runner, "-1", true, false) servicetest.Run(t, dsCache) From 83d6f2004cfb27340158a1e356e4f65c1ad46e43 Mon Sep 17 00:00:00 2001 From: Ryan Tinianov Date: Thu, 25 Apr 2024 11:19:55 -0400 Subject: [PATCH 14/34] Pass client to chain reader instead of the whole chain (#12967) --- core/services/relay/evm/chain_reader.go | 6 ++---- core/services/relay/evm/chain_reader_test.go | 15 ++++++--------- core/services/relay/evm/evm.go | 2 +- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/core/services/relay/evm/chain_reader.go b/core/services/relay/evm/chain_reader.go index e7035f4716f..df46e7636d2 100644 --- a/core/services/relay/evm/chain_reader.go +++ b/core/services/relay/evm/chain_reader.go @@ -16,8 +16,6 @@ import ( commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services" @@ -41,11 +39,11 @@ type chainReader struct { // NewChainReaderService is a constructor for ChainReader, returns nil if there is any error // Note that the ChainReaderService returned does not support anonymous events. -func NewChainReaderService(ctx context.Context, lggr logger.Logger, lp logpoller.LogPoller, chain legacyevm.Chain, config types.ChainReaderConfig) (ChainReaderService, error) { +func NewChainReaderService(ctx context.Context, lggr logger.Logger, lp logpoller.LogPoller, client evmclient.Client, config types.ChainReaderConfig) (ChainReaderService, error) { cr := &chainReader{ lggr: lggr.Named("ChainReader"), lp: lp, - client: chain.Client(), + client: client, contractBindings: contractBindings{}, parsed: &parsedTypes{encoderDefs: map[string]types.CodecEntry{}, decoderDefs: map[string]types.CodecEntry{}}, } diff --git a/core/services/relay/evm/chain_reader_test.go b/core/services/relay/evm/chain_reader_test.go index edca5c19b60..3a0d45b67c5 100644 --- a/core/services/relay/evm/chain_reader_test.go +++ b/core/services/relay/evm/chain_reader_test.go @@ -32,7 +32,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm/mocks" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/chain_reader_example" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" @@ -120,7 +119,7 @@ func triggerFourTopics(t *testing.T, it *chainReaderInterfaceTester, i1, i2, i3 } type chainReaderInterfaceTester struct { - chain *mocks.Chain + client client.Client address string address2 string chainConfig types.ChainReaderConfig @@ -157,12 +156,11 @@ func (it *chainReaderInterfaceTester) Setup(t *testing.T) { }) // can re-use the same chain for tests, just make new contract for each test - if it.chain != nil { + if it.client != nil { it.deployNewContracts(t) return } - it.chain = &mocks.Chain{} it.setupChainNoClient(t) testStruct := CreateTestStruct(0, it) @@ -240,7 +238,7 @@ func (it *chainReaderInterfaceTester) Setup(t *testing.T) { }, }, } - it.chain.On("Client").Return(client.NewSimulatedBackendClient(t, it.sim, big.NewInt(1337))) + it.client = client.NewSimulatedBackendClient(t, it.sim, big.NewInt(1337)) it.deployNewContracts(t) } @@ -270,10 +268,9 @@ func (it *chainReaderInterfaceTester) GetChainReader(t *testing.T) clcommontypes RpcBatchSize: 1, KeepFinalizedBlocksDepth: 10000, } - lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.SimulatedChainID, db, lggr), it.chain.Client(), lggr, lpOpts) + lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.SimulatedChainID, db, lggr), it.client, lggr, lpOpts) require.NoError(t, lp.Start(ctx)) - it.chain.On("LogPoller").Return(lp) - cr, err := evm.NewChainReaderService(ctx, lggr, lp, it.chain, it.chainConfig) + cr, err := evm.NewChainReaderService(ctx, lggr, lp, it.client, it.chainConfig) require.NoError(t, err) require.NoError(t, cr.Start(ctx)) it.cr = cr @@ -288,7 +285,7 @@ func (it *chainReaderInterfaceTester) TriggerEvent(t *testing.T, testStruct *Tes it.sendTxWithTestStruct(t, testStruct, (*chain_reader_example.LatestValueHolderTransactor).TriggerEvent) } -func (it *chainReaderInterfaceTester) GetBindings(t *testing.T) []clcommontypes.BoundContract { +func (it *chainReaderInterfaceTester) GetBindings(_ *testing.T) []clcommontypes.BoundContract { return []clcommontypes.BoundContract{ {Name: AnyContractName, Address: it.address, Pending: true}, {Name: AnySecondContractName, Address: it.address2, Pending: true}, diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index 2f30d40e28d..9097c217590 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -596,7 +596,7 @@ func (r *Relayer) NewMedianProvider(rargs commontypes.RelayArgs, pargs commontyp // allow fallback until chain reader is default and median contract is removed, but still log just in case var chainReaderService ChainReaderService if relayConfig.ChainReader != nil { - if chainReaderService, err = NewChainReaderService(ctx, lggr, r.chain.LogPoller(), r.chain, *relayConfig.ChainReader); err != nil { + if chainReaderService, err = NewChainReaderService(ctx, lggr, r.chain.LogPoller(), r.chain.Client(), *relayConfig.ChainReader); err != nil { return nil, err } From 274a988985e0530676bdfedbdb35dec4cb9fe8b2 Mon Sep 17 00:00:00 2001 From: Lei Date: Thu, 25 Apr 2024 09:14:48 -0700 Subject: [PATCH 15/34] use safe lib for approve (#12923) --- .changeset/dull-dingos-remember.md | 5 +++++ contracts/.changeset/shiny-dragons-sparkle.md | 5 +++++ .../dev/v2_3/AutomationRegistrar2_3.sol | 19 ++++++++++--------- .../automation_registrar_wrapper2_3.go | 2 +- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 5 files changed, 22 insertions(+), 11 deletions(-) create mode 100644 .changeset/dull-dingos-remember.md create mode 100644 contracts/.changeset/shiny-dragons-sparkle.md diff --git a/.changeset/dull-dingos-remember.md b/.changeset/dull-dingos-remember.md new file mode 100644 index 00000000000..7c1b748cff7 --- /dev/null +++ b/.changeset/dull-dingos-remember.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +use safe lib for approve #bugfix diff --git a/contracts/.changeset/shiny-dragons-sparkle.md b/contracts/.changeset/shiny-dragons-sparkle.md new file mode 100644 index 00000000000..7657b5f1446 --- /dev/null +++ b/contracts/.changeset/shiny-dragons-sparkle.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +use safe lib for approve #bugfix diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistrar2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistrar2_3.sol index ab9d7ae0b20..4284ba62f9d 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistrar2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistrar2_3.sol @@ -393,6 +393,8 @@ contract AutomationRegistrar2_3 is TypeAndVersionInterface, ConfirmedOwner, IERC /** * @dev register upkeep on AutomationRegistry contract and emit RegistrationApproved event + * @dev safeApprove is deprecated and removed from the latest (v5) OZ release, Use safeIncreaseAllowance when we upgrade OZ (we are on v4.8) + * @dev we stick to the safeApprove because of the older version (v4.8) of safeIncreaseAllowance can't handle USDT correctly, but newer version can */ function _approve(RegistrationParams memory params, bytes32 hash) private returns (uint256) { IAutomationRegistryMaster2_3 registry = s_registry; @@ -406,18 +408,17 @@ contract AutomationRegistrar2_3 is TypeAndVersionInterface, ConfirmedOwner, IERC params.triggerConfig, params.offchainConfig ); - bool success; + if (address(params.billingToken) == address(i_LINK)) { - success = i_LINK.transferAndCall(address(registry), params.amount, abi.encode(upkeepId)); - } else { - success = params.billingToken.approve(address(registry), params.amount); - if (success) { - registry.addFunds(upkeepId, params.amount); + bool success = i_LINK.transferAndCall(address(registry), params.amount, abi.encode(upkeepId)); + if (!success) { + revert TransferFailed(address(registry)); } + } else { + params.billingToken.safeApprove(address(registry), params.amount); + registry.addFunds(upkeepId, params.amount); } - if (!success) { - revert TransferFailed(address(registry)); - } + emit RegistrationApproved(hash, params.name, upkeepId); return upkeepId; } diff --git a/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go b/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go index 1f6c763d280..dd16a290b7c 100644 --- a/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go +++ b/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go @@ -58,7 +58,7 @@ type AutomationRegistrar23TriggerRegistrationStorage struct { var AutomationRegistrarMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"LINKAddress\",\"type\":\"address\"},{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"registry\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistrar2_3.InitialTriggerConfig[]\",\"name\":\"triggerConfigs\",\"type\":\"tuple[]\"},{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"minRegistrationFees\",\"type\":\"uint256[]\"},{\"internalType\":\"contractIWrappedNative\",\"name\":\"wrappedNativeToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"HashMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPayment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAdminAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBillingToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyAdminOrOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyLink\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RequestNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"AutoApproveAllowedSenderSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"displayName\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"RegistrationApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"RegistrationRejected\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"RegistrationRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"name\":\"TriggerConfigSet\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structAutomationRegistrar2_3.RegistrationParams\",\"name\":\"requestParams\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"cancel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"}],\"name\":\"getAutoApproveAllowedSender\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMinimumRegistrationAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"getPendingRequest\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRegistry\",\"outputs\":[{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"}],\"name\":\"getTriggerRegistrationDetails\",\"outputs\":[{\"components\":[{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"approvedCount\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistrar2_3.TriggerRegistrationStorage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_LINK\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_WRAPPED_NATIVE_TOKEN\",\"outputs\":[{\"internalType\":\"contractIWrappedNative\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structAutomationRegistrar2_3.RegistrationParams\",\"name\":\"requestParams\",\"type\":\"tuple\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"setAutoApproveAllowedSender\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"minBalances\",\"type\":\"uint256[]\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"name\":\"setTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60c06040523480156200001157600080fd5b5060405162003483380380620034838339810160408190526200003491620005db565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be8162000183565b5050506001600160a01b03808716608052811660a052620000e18584846200022e565b60005b84518110156200017657620001618582815181106200010757620001076200076d565b6020026020010151600001518683815181106200012857620001286200076d565b6020026020010151602001518784815181106200014957620001496200076d565b6020026020010151604001516200032a60201b60201c565b806200016d8162000783565b915050620000e4565b5050505050505062000804565b336001600160a01b03821603620001dd5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b62000238620003d8565b80518251146200025b57604051630dfe930960e41b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b03851617905560005b8251811015620002fb578181815181106200029857620002986200076d565b602002602001015160046000858481518110620002b957620002b96200076d565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055508080620002f29062000783565b91505062000279565b506040517fb9b6902016bd1219d5fa6161243b61e7e9f7f959526dd94ef8fa3e403bf881c390600090a1505050565b62000334620003d8565b60ff83166000908152600660205260409020805483919060ff19166001836002811115620003665762000366620007ab565b021790555060ff831660009081526006602052604090819020805464ffffffff00191661010063ffffffff851602179055517f830a6d06a4e2caac67eba04323de22bdb04f032dd8b3d6a0c52b503d9a7036a390620003cb90859085908590620007c1565b60405180910390a1505050565b6000546001600160a01b03163314620004345760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000082565b565b6001600160a01b03811681146200044c57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b03811182821017156200048a576200048a6200044f565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620004bb57620004bb6200044f565b604052919050565b60006001600160401b03821115620004df57620004df6200044f565b5060051b60200190565b600082601f830112620004fb57600080fd5b81516020620005146200050e83620004c3565b62000490565b82815260059290921b840181019181810190868411156200053457600080fd5b8286015b848110156200055c5780516200054e8162000436565b835291830191830162000538565b509695505050505050565b600082601f8301126200057957600080fd5b815160206200058c6200050e83620004c3565b82815260059290921b84018101918181019086841115620005ac57600080fd5b8286015b848110156200055c5780518352918301918301620005b0565b8051620005d68162000436565b919050565b60008060008060008060c08789031215620005f557600080fd5b8651620006028162000436565b80965050602080880151620006178162000436565b60408901519096506001600160401b03808211156200063557600080fd5b818a0191508a601f8301126200064a57600080fd5b81516200065b6200050e82620004c3565b81815260609091028301840190848101908d8311156200067a57600080fd5b938501935b8285101562000701576060858f0312156200069a5760008081fd5b620006a462000465565b855160ff81168114620006b75760008081fd5b81528587015160038110620006cc5760008081fd5b81880152604086015163ffffffff81168114620006e95760008081fd5b6040820152825260609490940193908501906200067f565b60608d015190995094505050808311156200071b57600080fd5b620007298b848c01620004e9565b955060808a01519250808311156200074057600080fd5b50506200075089828a0162000567565b9250506200076160a08801620005c9565b90509295509295509295565b634e487b7160e01b600052603260045260246000fd5b600060018201620007a457634e487b7160e01b600052601160045260246000fd5b5060010190565b634e487b7160e01b600052602160045260246000fd5b60ff841681526060810160038410620007ea57634e487b7160e01b600052602160045260246000fd5b83602083015263ffffffff83166040830152949350505050565b60805160a051612c2f620008546000396000818161027b015281816105a601526106390152600081816104b301528181610a0301528181610a6c0152818161168501526116dc0152612c2f6000f3fe6080604052600436106101295760003560e01c806388b12d55116100a5578063accb832311610074578063befdae4611610059578063befdae46146104a1578063c4d252f5146104d5578063f2fde38b146104f557600080fd5b8063accb832314610461578063b5ff5b411461048157600080fd5b806388b12d55146103085780638da5cb5b146103d3578063a2b1ff94146103fe578063a4c0ed361461044157600080fd5b80635ab1bd53116100fc5780636bf7d75f116100e15780636bf7d75f1461026957806379ba50971461029d5780637e776f7f146102b257600080fd5b80635ab1bd53146101fd57806366ab87f91461024957600080fd5b8063181f5a771461012e578063212d08841461018d5780632ce3a14a146101ba578063367b9b4f146101db575b600080fd5b34801561013a57600080fd5b506101776040518060400160405280601981526020017f4175746f6d6174696f6e52656769737472617220322e332e300000000000000081525081565b6040516101849190611e6f565b60405180910390f35b34801561019957600080fd5b506101ad6101a8366004611e9f565b610515565b6040516101849190611f24565b6101cd6101c836600461223b565b6105a2565b604051908152602001610184565b3480156101e757600080fd5b506101fb6101f636600461227e565b610710565b005b34801561020957600080fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610184565b34801561025557600080fd5b506101fb610264366004612346565b6107a2565b34801561027557600080fd5b506102247f000000000000000000000000000000000000000000000000000000000000000081565b3480156102a957600080fd5b506101fb6108e9565b3480156102be57600080fd5b506102f86102cd36600461241c565b73ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205460ff1690565b6040519015158152602001610184565b34801561031457600080fd5b5061039a610323366004612439565b6000908152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff169483018590526001909301549092169301929092529091565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526bffffffffffffffffffffffff909116602083015201610184565b3480156103df57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610224565b34801561040a57600080fd5b506101cd61041936600461241c565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b34801561044d57600080fd5b506101fb61045c366004612452565b6109eb565b34801561046d57600080fd5b506101fb61047c3660046124db565b610b19565b34801561048d57600080fd5b506101fb61049c366004612526565b610c84565b3480156104ad57600080fd5b506102247f000000000000000000000000000000000000000000000000000000000000000081565b3480156104e157600080fd5b506101fb6104f0366004612439565b610d63565b34801561050157600080fd5b506101fb61051036600461241c565b610f2a565b60408051606080820183526000808352602080840182905283850182905260ff86811683526006909152908490208451928301909452835492939192839116600281111561056557610565611eba565b600281111561057657610576611eba565b8152905463ffffffff610100820481166020840152650100000000009091041660409091015292915050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168260a0015173ffffffffffffffffffffffffffffffffffffffff1614801561060257503415155b156106bd5761061034610f3e565b82602001906bffffffffffffffffffffffff1690816bffffffffffffffffffffffff16815250507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561069f57600080fd5b505af11580156106b3573d6000803e3d6000fd5b5050505050610700565b610700333084602001516bffffffffffffffffffffffff168560a0015173ffffffffffffffffffffffffffffffffffffffff16610fe0909392919063ffffffff16565b61070a82336110c2565b92915050565b610718611529565b73ffffffffffffffffffffffffffffffffffffffff821660008181526003602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591519182527f20c6237dac83526a849285a9f79d08a483291bdd3a056a0ef9ae94ecee1ad356910160405180910390a25050565b6107aa611529565b80518251146107e5576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851617905560005b82518110156108ba578181815181106108435761084361256f565b6020026020010151600460008584815181106108615761086161256f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080806108b2906125cd565b915050610828565b506040517fb9b6902016bd1219d5fa6161243b61e7e9f7f959526dd94ef8fa3e403bf881c390600090a1505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461096f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610a5a576040517f018d10be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a688284018461223b565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168160a0015173ffffffffffffffffffffffffffffffffffffffff1614610af3576040517f018d10be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6bffffffffffffffffffffffff84166020820152610b1181866110c2565b505050505050565b610b21611529565b6000818152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff16948301949094526001909201549092169282019290925290610bcd576040517f4b13b31e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083604051602001610be091906126b9565b604051602081830303815290604052805190602001209050808314610c31576040517f3f4d605300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083815260056020526040812090815560010180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610c7d610c7785612875565b826115ac565b5050505050565b610c8c611529565b60ff8316600090815260066020526040902080548391907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836002811115610cd957610cd9611eba565b021790555060ff83166000908152600660205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff1661010063ffffffff851602179055517f830a6d06a4e2caac67eba04323de22bdb04f032dd8b3d6a0c52b503d9a7036a390610d5690859085908590612881565b60405180910390a1505050565b6000818152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff16948301949094526001909201549092169282019290925290331480610dfd575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610e33576040517f61685c2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16610e81576040517f4b13b31e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040808320928355600190920180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905582519083015191830151610efb9273ffffffffffffffffffffffffffffffffffffffff90911691906bffffffffffffffffffffffff1661198f565b60405182907f3663fb28ebc87645eb972c9dad8521bf665c623f287e79f1c56f1eb374b82a2290600090a25050565b610f32611529565b610f3b816119ea565b50565b60006bffffffffffffffffffffffff821115610fdc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610966565b5090565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526110bc9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611adf565b50505050565b60a082015173ffffffffffffffffffffffffffffffffffffffff166000908152600460209081526040822054908401516bffffffffffffffffffffffff161015611138576040517fcd1c886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604083015173ffffffffffffffffffffffffffffffffffffffff16611189576040517f05bb467c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025460a08401516040517fa538b2eb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063a538b2eb90602401602060405180830381865afa1580156111fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061122191906128ac565b611257576040517f1183afea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360405160200161126a91906128c9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152600590935291205490915073ffffffffffffffffffffffffffffffffffffffff16156112fd576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836000015173ffffffffffffffffffffffffffffffffffffffff16817f7684390ebb103102f7f48c71439c2408713f8d437782a6fab2756acc0e42c1b78660c001518760e00151886060015189604001518a608001518b61012001518c61014001518d61010001518e6020015160405161137f99989796959493929190612a35565b60405180910390a3608084015160ff908116600090815260066020526040808220815160608101909252805492936114029383911660028111156113c5576113c5611eba565b60028111156113d6576113d6611eba565b8152905463ffffffff610100820481166020840152650100000000009091041660409091015285611beb565b1561146a57608085015160ff166000908152600660205260409020805465010000000000900463ffffffff1690600561143a83612af0565b91906101000a81548163ffffffff021916908363ffffffff1602179055505061146385836115ac565b9050611521565b604080516060810182528682015173ffffffffffffffffffffffffffffffffffffffff90811682526020808901516bffffffffffffffffffffffff90811682850190815260a08b01518416858701908152600089815260059094529590922093519151167401000000000000000000000000000000000000000002908216178255915160019091018054919092167fffffffffffffffffffffffff0000000000000000000000000000000000000000919091161790555b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146115aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610966565b565b60025482516060840151604080860151608087015160a08801516101008901516101208a01516101408b015195517fc62cf68400000000000000000000000000000000000000000000000000000000815260009973ffffffffffffffffffffffffffffffffffffffff16988a988a9863c62cf6849861163c98939792969095939492939092909190600401612b13565b6020604051808303816000875af115801561165b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061167f9190612ba1565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168660a0015173ffffffffffffffffffffffffffffffffffffffff16036117a6577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16634000aea08488602001518560405160200161172f91815260200190565b6040516020818303038152906040526040518463ffffffff1660e01b815260040161175c93929190612bba565b6020604051808303816000875af115801561177b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179f91906128ac565b90506118fa565b60a086015160208701516040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526bffffffffffffffffffffffff909216602482015291169063095ea7b3906044016020604051808303816000875af1158015611833573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185791906128ac565b905080156118fa5760208601516040517f948108f7000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff909116602482015273ffffffffffffffffffffffffffffffffffffffff84169063948108f790604401600060405180830381600087803b1580156118e157600080fd5b505af11580156118f5573d6000803e3d6000fd5b505050505b80611949576040517f39f1c8d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610966565b81857fb9a292fb7e3edd920cd2d2829a3615a640c43fd7de0a0820aa0668feb4c37d4b8860c0015160405161197e9190611e6f565b60405180910390a350949350505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526119e59084907fa9059cbb000000000000000000000000000000000000000000000000000000009060640161103a565b505050565b3373ffffffffffffffffffffffffffffffffffffffff821603611a69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610966565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611b41826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611c909092919063ffffffff16565b8051909150156119e55780806020019051810190611b5f91906128ac565b6119e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610966565b60008083516002811115611c0157611c01611eba565b03611c0e5750600061070a565b600183516002811115611c2357611c23611eba565b148015611c56575073ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604090205460ff16155b15611c635750600061070a565b826020015163ffffffff16836040015163ffffffff161015611c875750600161070a565b50600092915050565b60606115218484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051611cc49190612c06565b60006040518083038185875af1925050503d8060008114611d01576040519150601f19603f3d011682016040523d82523d6000602084013e611d06565b606091505b5091509150611d1787838387611d22565b979650505050505050565b60608315611db8578251600003611db15773ffffffffffffffffffffffffffffffffffffffff85163b611db1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610966565b5081611521565b6115218383815115611dcd5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109669190611e6f565b60005b83811015611e1c578181015183820152602001611e04565b50506000910152565b60008151808452611e3d816020860160208601611e01565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611e826020830184611e25565b9392505050565b803560ff81168114611e9a57600080fd5b919050565b600060208284031215611eb157600080fd5b611e8282611e89565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60038110611f20577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b6000606082019050611f37828451611ee9565b602083015163ffffffff8082166020850152806040860151166040850152505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610160810167ffffffffffffffff81118282101715611fb057611fb0611f5d565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611ffd57611ffd611f5d565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f3b57600080fd5b8035611e9a81612005565b80356bffffffffffffffffffffffff81168114611e9a57600080fd5b803563ffffffff81168114611e9a57600080fd5b600082601f83011261207357600080fd5b813567ffffffffffffffff81111561208d5761208d611f5d565b6120be60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611fb6565b8181528460208386010111156120d357600080fd5b816020850160208301376000918101602001919091529392505050565b6000610160828403121561210357600080fd5b61210b611f8c565b905061211682612027565b815261212460208301612032565b602082015261213560408301612027565b60408201526121466060830161204e565b606082015261215760808301611e89565b608082015261216860a08301612027565b60a082015260c082013567ffffffffffffffff8082111561218857600080fd5b61219485838601612062565b60c084015260e08401359150808211156121ad57600080fd5b6121b985838601612062565b60e0840152610100915081840135818111156121d457600080fd5b6121e086828701612062565b8385015250610120915081840135818111156121fb57600080fd5b61220786828701612062565b83850152506101409150818401358181111561222257600080fd5b61222e86828701612062565b8385015250505092915050565b60006020828403121561224d57600080fd5b813567ffffffffffffffff81111561226457600080fd5b611521848285016120f0565b8015158114610f3b57600080fd5b6000806040838503121561229157600080fd5b823561229c81612005565b915060208301356122ac81612270565b809150509250929050565b600067ffffffffffffffff8211156122d1576122d1611f5d565b5060051b60200190565b600082601f8301126122ec57600080fd5b813560206123016122fc836122b7565b611fb6565b82815260059290921b8401810191818101908684111561232057600080fd5b8286015b8481101561233b5780358352918301918301612324565b509695505050505050565b60008060006060848603121561235b57600080fd5b833561236681612005565b925060208481013567ffffffffffffffff8082111561238457600080fd5b818701915087601f83011261239857600080fd5b81356123a66122fc826122b7565b81815260059190911b8301840190848101908a8311156123c557600080fd5b938501935b828510156123ec5784356123dd81612005565b825293850193908501906123ca565b96505050604087013592508083111561240457600080fd5b5050612412868287016122db565b9150509250925092565b60006020828403121561242e57600080fd5b8135611e8281612005565b60006020828403121561244b57600080fd5b5035919050565b6000806000806060858703121561246857600080fd5b843561247381612005565b935060208501359250604085013567ffffffffffffffff8082111561249757600080fd5b818701915087601f8301126124ab57600080fd5b8135818111156124ba57600080fd5b8860208285010111156124cc57600080fd5b95989497505060200194505050565b600080604083850312156124ee57600080fd5b823567ffffffffffffffff81111561250557600080fd5b8301610160818603121561251857600080fd5b946020939093013593505050565b60008060006060848603121561253b57600080fd5b61254484611e89565b925060208401356003811061255857600080fd5b91506125666040850161204e565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036125fe576125fe61259e565b5060010190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261263a57600080fd5b830160208101925035905067ffffffffffffffff81111561265a57600080fd5b80360382131561266957600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526126e7602082016126cd84612027565b73ffffffffffffffffffffffffffffffffffffffff169052565b60006126f560208401612032565b6bffffffffffffffffffffffff811660408401525061271660408401612027565b73ffffffffffffffffffffffffffffffffffffffff811660608401525061273f6060840161204e565b63ffffffff811660808401525061275860808401611e89565b60ff811660a08401525061276e60a08401612027565b73ffffffffffffffffffffffffffffffffffffffff811660c08401525061279860c0840184612605565b6101608060e08601526127b061018086018385612670565b92506127bf60e0870187612605565b92507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06101008188870301818901526127f9868685612670565b9550612807818a018a612605565b9550925050610120818887030181890152612823868685612670565b9550612831818a018a612605565b955092505061014081888703018189015261284d868685612670565b955061285b818a018a612605565b955092505080878603018388015250611d17848483612670565b600061070a36836120f0565b60ff84168152606081016128986020830185611ee9565b63ffffffff83166040830152949350505050565b6000602082840312156128be57600080fd5b8151611e8281612270565b602081526128f060208201835173ffffffffffffffffffffffffffffffffffffffff169052565b6000602083015161291160408401826bffffffffffffffffffffffff169052565b50604083015173ffffffffffffffffffffffffffffffffffffffff8116606084015250606083015163ffffffff8116608084015250608083015160ff811660a08401525060a083015173ffffffffffffffffffffffffffffffffffffffff811660c08401525060c08301516101608060e0850152612993610180850183611e25565b915060e08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06101008187860301818801526129d18584611e25565b9450808801519250506101208187860301818801526129f08584611e25565b945080880151925050610140818786030181880152612a0f8584611e25565b908801518782039092018488015293509050612a2b8382611e25565b9695505050505050565b6000610120808352612a498184018d611e25565b90508281036020840152612a5d818c611e25565b905063ffffffff8a16604084015273ffffffffffffffffffffffffffffffffffffffff8916606084015260ff8816608084015282810360a0840152612aa28188611e25565b905082810360c0840152612ab68187611e25565b905082810360e0840152612aca8186611e25565b9150506bffffffffffffffffffffffff83166101008301529a9950505050505050505050565b600063ffffffff808316818103612b0957612b0961259e565b6001019392505050565b600061010073ffffffffffffffffffffffffffffffffffffffff808c16845263ffffffff8b166020850152808a16604085015260ff891660608501528088166080850152508060a0840152612b6a81840187611e25565b905082810360c0840152612b7e8186611e25565b905082810360e0840152612b928185611e25565b9b9a5050505050505050505050565b600060208284031215612bb357600080fd5b5051919050565b73ffffffffffffffffffffffffffffffffffffffff841681526bffffffffffffffffffffffff83166020820152606060408201526000612bfd6060830184611e25565b95945050505050565b60008251612c18818460208701611e01565b919091019291505056fea164736f6c6343000813000a", + Bin: "0x60c06040523480156200001157600080fd5b506040516200358d3803806200358d8339810160408190526200003491620005db565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be8162000183565b5050506001600160a01b03808716608052811660a052620000e18584846200022e565b60005b84518110156200017657620001618582815181106200010757620001076200076d565b6020026020010151600001518683815181106200012857620001286200076d565b6020026020010151602001518784815181106200014957620001496200076d565b6020026020010151604001516200032a60201b60201c565b806200016d8162000783565b915050620000e4565b5050505050505062000804565b336001600160a01b03821603620001dd5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b62000238620003d8565b80518251146200025b57604051630dfe930960e41b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b03851617905560005b8251811015620002fb578181815181106200029857620002986200076d565b602002602001015160046000858481518110620002b957620002b96200076d565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055508080620002f29062000783565b91505062000279565b506040517fb9b6902016bd1219d5fa6161243b61e7e9f7f959526dd94ef8fa3e403bf881c390600090a1505050565b62000334620003d8565b60ff83166000908152600660205260409020805483919060ff19166001836002811115620003665762000366620007ab565b021790555060ff831660009081526006602052604090819020805464ffffffff00191661010063ffffffff851602179055517f830a6d06a4e2caac67eba04323de22bdb04f032dd8b3d6a0c52b503d9a7036a390620003cb90859085908590620007c1565b60405180910390a1505050565b6000546001600160a01b03163314620004345760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000082565b565b6001600160a01b03811681146200044c57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b03811182821017156200048a576200048a6200044f565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620004bb57620004bb6200044f565b604052919050565b60006001600160401b03821115620004df57620004df6200044f565b5060051b60200190565b600082601f830112620004fb57600080fd5b81516020620005146200050e83620004c3565b62000490565b82815260059290921b840181019181810190868411156200053457600080fd5b8286015b848110156200055c5780516200054e8162000436565b835291830191830162000538565b509695505050505050565b600082601f8301126200057957600080fd5b815160206200058c6200050e83620004c3565b82815260059290921b84018101918181019086841115620005ac57600080fd5b8286015b848110156200055c5780518352918301918301620005b0565b8051620005d68162000436565b919050565b60008060008060008060c08789031215620005f557600080fd5b8651620006028162000436565b80965050602080880151620006178162000436565b60408901519096506001600160401b03808211156200063557600080fd5b818a0191508a601f8301126200064a57600080fd5b81516200065b6200050e82620004c3565b81815260609091028301840190848101908d8311156200067a57600080fd5b938501935b8285101562000701576060858f0312156200069a5760008081fd5b620006a462000465565b855160ff81168114620006b75760008081fd5b81528587015160038110620006cc5760008081fd5b81880152604086015163ffffffff81168114620006e95760008081fd5b6040820152825260609490940193908501906200067f565b60608d015190995094505050808311156200071b57600080fd5b620007298b848c01620004e9565b955060808a01519250808311156200074057600080fd5b50506200075089828a0162000567565b9250506200076160a08801620005c9565b90509295509295509295565b634e487b7160e01b600052603260045260246000fd5b600060018201620007a457634e487b7160e01b600052601160045260246000fd5b5060010190565b634e487b7160e01b600052602160045260246000fd5b60ff841681526060810160038410620007ea57634e487b7160e01b600052602160045260246000fd5b83602083015263ffffffff83166040830152949350505050565b60805160a051612d39620008546000396000818161027b015281816105a601526106390152600081816104b301528181610a0301528181610a6c0152818161168301526116dc0152612d396000f3fe6080604052600436106101295760003560e01c806388b12d55116100a5578063accb832311610074578063befdae4611610059578063befdae46146104a1578063c4d252f5146104d5578063f2fde38b146104f557600080fd5b8063accb832314610461578063b5ff5b411461048157600080fd5b806388b12d55146103085780638da5cb5b146103d3578063a2b1ff94146103fe578063a4c0ed361461044157600080fd5b80635ab1bd53116100fc5780636bf7d75f116100e15780636bf7d75f1461026957806379ba50971461029d5780637e776f7f146102b257600080fd5b80635ab1bd53146101fd57806366ab87f91461024957600080fd5b8063181f5a771461012e578063212d08841461018d5780632ce3a14a146101ba578063367b9b4f146101db575b600080fd5b34801561013a57600080fd5b506101776040518060400160405280601981526020017f4175746f6d6174696f6e52656769737472617220322e332e300000000000000081525081565b6040516101849190611f79565b60405180910390f35b34801561019957600080fd5b506101ad6101a8366004611fa9565b610515565b604051610184919061202e565b6101cd6101c8366004612345565b6105a2565b604051908152602001610184565b3480156101e757600080fd5b506101fb6101f6366004612388565b610710565b005b34801561020957600080fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610184565b34801561025557600080fd5b506101fb610264366004612450565b6107a2565b34801561027557600080fd5b506102247f000000000000000000000000000000000000000000000000000000000000000081565b3480156102a957600080fd5b506101fb6108e9565b3480156102be57600080fd5b506102f86102cd366004612526565b73ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205460ff1690565b6040519015158152602001610184565b34801561031457600080fd5b5061039a610323366004612543565b6000908152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff169483018590526001909301549092169301929092529091565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526bffffffffffffffffffffffff909116602083015201610184565b3480156103df57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610224565b34801561040a57600080fd5b506101cd610419366004612526565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b34801561044d57600080fd5b506101fb61045c36600461255c565b6109eb565b34801561046d57600080fd5b506101fb61047c3660046125e5565b610b19565b34801561048d57600080fd5b506101fb61049c366004612630565b610c84565b3480156104ad57600080fd5b506102247f000000000000000000000000000000000000000000000000000000000000000081565b3480156104e157600080fd5b506101fb6104f0366004612543565b610d63565b34801561050157600080fd5b506101fb610510366004612526565b610f2a565b60408051606080820183526000808352602080840182905283850182905260ff86811683526006909152908490208451928301909452835492939192839116600281111561056557610565611fc4565b600281111561057657610576611fc4565b8152905463ffffffff610100820481166020840152650100000000009091041660409091015292915050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168260a0015173ffffffffffffffffffffffffffffffffffffffff1614801561060257503415155b156106bd5761061034610f3e565b82602001906bffffffffffffffffffffffff1690816bffffffffffffffffffffffff16815250507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561069f57600080fd5b505af11580156106b3573d6000803e3d6000fd5b5050505050610700565b610700333084602001516bffffffffffffffffffffffff168560a0015173ffffffffffffffffffffffffffffffffffffffff16610fe0909392919063ffffffff16565b61070a82336110c2565b92915050565b610718611529565b73ffffffffffffffffffffffffffffffffffffffff821660008181526003602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591519182527f20c6237dac83526a849285a9f79d08a483291bdd3a056a0ef9ae94ecee1ad356910160405180910390a25050565b6107aa611529565b80518251146107e5576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851617905560005b82518110156108ba5781818151811061084357610843612679565b60200260200101516004600085848151811061086157610861612679565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080806108b2906126d7565b915050610828565b506040517fb9b6902016bd1219d5fa6161243b61e7e9f7f959526dd94ef8fa3e403bf881c390600090a1505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461096f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610a5a576040517f018d10be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a6882840184612345565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168160a0015173ffffffffffffffffffffffffffffffffffffffff1614610af3576040517f018d10be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6bffffffffffffffffffffffff84166020820152610b1181866110c2565b505050505050565b610b21611529565b6000818152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff16948301949094526001909201549092169282019290925290610bcd576040517f4b13b31e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083604051602001610be091906127c3565b604051602081830303815290604052805190602001209050808314610c31576040517f3f4d605300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083815260056020526040812090815560010180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610c7d610c778561297f565b826115ac565b5050505050565b610c8c611529565b60ff8316600090815260066020526040902080548391907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836002811115610cd957610cd9611fc4565b021790555060ff83166000908152600660205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff1661010063ffffffff851602179055517f830a6d06a4e2caac67eba04323de22bdb04f032dd8b3d6a0c52b503d9a7036a390610d569085908590859061298b565b60405180910390a1505050565b6000818152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff16948301949094526001909201549092169282019290925290331480610dfd575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610e33576040517f61685c2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16610e81576040517f4b13b31e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040808320928355600190920180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905582519083015191830151610efb9273ffffffffffffffffffffffffffffffffffffffff90911691906bffffffffffffffffffffffff16611917565b60405182907f3663fb28ebc87645eb972c9dad8521bf665c623f287e79f1c56f1eb374b82a2290600090a25050565b610f32611529565b610f3b81611972565b50565b60006bffffffffffffffffffffffff821115610fdc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610966565b5090565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526110bc9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611a67565b50505050565b60a082015173ffffffffffffffffffffffffffffffffffffffff166000908152600460209081526040822054908401516bffffffffffffffffffffffff161015611138576040517fcd1c886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604083015173ffffffffffffffffffffffffffffffffffffffff16611189576040517f05bb467c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025460a08401516040517fa538b2eb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063a538b2eb90602401602060405180830381865afa1580156111fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061122191906129b6565b611257576040517f1183afea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360405160200161126a91906129d3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152600590935291205490915073ffffffffffffffffffffffffffffffffffffffff16156112fd576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836000015173ffffffffffffffffffffffffffffffffffffffff16817f7684390ebb103102f7f48c71439c2408713f8d437782a6fab2756acc0e42c1b78660c001518760e00151886060015189604001518a608001518b61012001518c61014001518d61010001518e6020015160405161137f99989796959493929190612b3f565b60405180910390a3608084015160ff908116600090815260066020526040808220815160608101909252805492936114029383911660028111156113c5576113c5611fc4565b60028111156113d6576113d6611fc4565b8152905463ffffffff610100820481166020840152650100000000009091041660409091015285611b73565b1561146a57608085015160ff166000908152600660205260409020805465010000000000900463ffffffff1690600561143a83612bfa565b91906101000a81548163ffffffff021916908363ffffffff1602179055505061146385836115ac565b9050611521565b604080516060810182528682015173ffffffffffffffffffffffffffffffffffffffff90811682526020808901516bffffffffffffffffffffffff90811682850190815260a08b01518416858701908152600089815260059094529590922093519151167401000000000000000000000000000000000000000002908216178255915160019091018054919092167fffffffffffffffffffffffff0000000000000000000000000000000000000000919091161790555b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146115aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610966565b565b60025482516060840151604080860151608087015160a08801516101008901516101208a01516101408b015195517fc62cf68400000000000000000000000000000000000000000000000000000000815260009973ffffffffffffffffffffffffffffffffffffffff16988a988a9863c62cf6849861163c98939792969095939492939092909190600401612c1d565b6020604051808303816000875af115801561165b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061167f9190612cab565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168560a0015173ffffffffffffffffffffffffffffffffffffffff16036117f65760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16634000aea08488602001518560405160200161172f91815260200190565b6040516020818303038152906040526040518463ffffffff1660e01b815260040161175c93929190612cc4565b6020604051808303816000875af115801561177b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179f91906129b6565b9050806117f0576040517f39f1c8d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610966565b506118d2565b6118378286602001516bffffffffffffffffffffffff168760a0015173ffffffffffffffffffffffffffffffffffffffff16611c189092919063ffffffff16565b60208501516040517f948108f7000000000000000000000000000000000000000000000000000000008152600481018390526bffffffffffffffffffffffff909116602482015273ffffffffffffffffffffffffffffffffffffffff83169063948108f790604401600060405180830381600087803b1580156118b957600080fd5b505af11580156118cd573d6000803e3d6000fd5b505050505b80847fb9a292fb7e3edd920cd2d2829a3615a640c43fd7de0a0820aa0668feb4c37d4b8760c001516040516119079190611f79565b60405180910390a3949350505050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905261196d9084907fa9059cbb000000000000000000000000000000000000000000000000000000009060640161103a565b505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036119f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610966565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611ac9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611d9a9092919063ffffffff16565b80519091501561196d5780806020019051810190611ae791906129b6565b61196d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610966565b60008083516002811115611b8957611b89611fc4565b03611b965750600061070a565b600183516002811115611bab57611bab611fc4565b148015611bde575073ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604090205460ff16155b15611beb5750600061070a565b826020015163ffffffff16836040015163ffffffff161015611c0f5750600161070a565b50600092915050565b801580611cb857506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611c92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cb69190612cab565b155b611d44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610966565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905261196d9084907f095ea7b3000000000000000000000000000000000000000000000000000000009060640161103a565b60606115218484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051611dce9190612d10565b60006040518083038185875af1925050503d8060008114611e0b576040519150601f19603f3d011682016040523d82523d6000602084013e611e10565b606091505b5091509150611e2187838387611e2c565b979650505050505050565b60608315611ec2578251600003611ebb5773ffffffffffffffffffffffffffffffffffffffff85163b611ebb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610966565b5081611521565b6115218383815115611ed75781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109669190611f79565b60005b83811015611f26578181015183820152602001611f0e565b50506000910152565b60008151808452611f47816020860160208601611f0b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611f8c6020830184611f2f565b9392505050565b803560ff81168114611fa457600080fd5b919050565b600060208284031215611fbb57600080fd5b611f8c82611f93565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6003811061202a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b6000606082019050612041828451611ff3565b602083015163ffffffff8082166020850152806040860151166040850152505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610160810167ffffffffffffffff811182821017156120ba576120ba612067565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561210757612107612067565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f3b57600080fd5b8035611fa48161210f565b80356bffffffffffffffffffffffff81168114611fa457600080fd5b803563ffffffff81168114611fa457600080fd5b600082601f83011261217d57600080fd5b813567ffffffffffffffff81111561219757612197612067565b6121c860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016120c0565b8181528460208386010111156121dd57600080fd5b816020850160208301376000918101602001919091529392505050565b6000610160828403121561220d57600080fd5b612215612096565b905061222082612131565b815261222e6020830161213c565b602082015261223f60408301612131565b604082015261225060608301612158565b606082015261226160808301611f93565b608082015261227260a08301612131565b60a082015260c082013567ffffffffffffffff8082111561229257600080fd5b61229e8583860161216c565b60c084015260e08401359150808211156122b757600080fd5b6122c38583860161216c565b60e0840152610100915081840135818111156122de57600080fd5b6122ea8682870161216c565b83850152506101209150818401358181111561230557600080fd5b6123118682870161216c565b83850152506101409150818401358181111561232c57600080fd5b6123388682870161216c565b8385015250505092915050565b60006020828403121561235757600080fd5b813567ffffffffffffffff81111561236e57600080fd5b611521848285016121fa565b8015158114610f3b57600080fd5b6000806040838503121561239b57600080fd5b82356123a68161210f565b915060208301356123b68161237a565b809150509250929050565b600067ffffffffffffffff8211156123db576123db612067565b5060051b60200190565b600082601f8301126123f657600080fd5b8135602061240b612406836123c1565b6120c0565b82815260059290921b8401810191818101908684111561242a57600080fd5b8286015b84811015612445578035835291830191830161242e565b509695505050505050565b60008060006060848603121561246557600080fd5b83356124708161210f565b925060208481013567ffffffffffffffff8082111561248e57600080fd5b818701915087601f8301126124a257600080fd5b81356124b0612406826123c1565b81815260059190911b8301840190848101908a8311156124cf57600080fd5b938501935b828510156124f65784356124e78161210f565b825293850193908501906124d4565b96505050604087013592508083111561250e57600080fd5b505061251c868287016123e5565b9150509250925092565b60006020828403121561253857600080fd5b8135611f8c8161210f565b60006020828403121561255557600080fd5b5035919050565b6000806000806060858703121561257257600080fd5b843561257d8161210f565b935060208501359250604085013567ffffffffffffffff808211156125a157600080fd5b818701915087601f8301126125b557600080fd5b8135818111156125c457600080fd5b8860208285010111156125d657600080fd5b95989497505060200194505050565b600080604083850312156125f857600080fd5b823567ffffffffffffffff81111561260f57600080fd5b8301610160818603121561262257600080fd5b946020939093013593505050565b60008060006060848603121561264557600080fd5b61264e84611f93565b925060208401356003811061266257600080fd5b915061267060408501612158565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612708576127086126a8565b5060010190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261274457600080fd5b830160208101925035905067ffffffffffffffff81111561276457600080fd5b80360382131561277357600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526127f1602082016127d784612131565b73ffffffffffffffffffffffffffffffffffffffff169052565b60006127ff6020840161213c565b6bffffffffffffffffffffffff811660408401525061282060408401612131565b73ffffffffffffffffffffffffffffffffffffffff811660608401525061284960608401612158565b63ffffffff811660808401525061286260808401611f93565b60ff811660a08401525061287860a08401612131565b73ffffffffffffffffffffffffffffffffffffffff811660c0840152506128a260c084018461270f565b6101608060e08601526128ba6101808601838561277a565b92506128c960e087018761270f565b92507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061010081888703018189015261290386868561277a565b9550612911818a018a61270f565b955092505061012081888703018189015261292d86868561277a565b955061293b818a018a61270f565b955092505061014081888703018189015261295786868561277a565b9550612965818a018a61270f565b955092505080878603018388015250611e2184848361277a565b600061070a36836121fa565b60ff84168152606081016129a26020830185611ff3565b63ffffffff83166040830152949350505050565b6000602082840312156129c857600080fd5b8151611f8c8161237a565b602081526129fa60208201835173ffffffffffffffffffffffffffffffffffffffff169052565b60006020830151612a1b60408401826bffffffffffffffffffffffff169052565b50604083015173ffffffffffffffffffffffffffffffffffffffff8116606084015250606083015163ffffffff8116608084015250608083015160ff811660a08401525060a083015173ffffffffffffffffffffffffffffffffffffffff811660c08401525060c08301516101608060e0850152612a9d610180850183611f2f565b915060e08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610100818786030181880152612adb8584611f2f565b945080880151925050610120818786030181880152612afa8584611f2f565b945080880151925050610140818786030181880152612b198584611f2f565b908801518782039092018488015293509050612b358382611f2f565b9695505050505050565b6000610120808352612b538184018d611f2f565b90508281036020840152612b67818c611f2f565b905063ffffffff8a16604084015273ffffffffffffffffffffffffffffffffffffffff8916606084015260ff8816608084015282810360a0840152612bac8188611f2f565b905082810360c0840152612bc08187611f2f565b905082810360e0840152612bd48186611f2f565b9150506bffffffffffffffffffffffff83166101008301529a9950505050505050505050565b600063ffffffff808316818103612c1357612c136126a8565b6001019392505050565b600061010073ffffffffffffffffffffffffffffffffffffffff808c16845263ffffffff8b166020850152808a16604085015260ff891660608501528088166080850152508060a0840152612c7481840187611f2f565b905082810360c0840152612c888186611f2f565b905082810360e0840152612c9c8185611f2f565b9b9a5050505050505050505050565b600060208284031215612cbd57600080fd5b5051919050565b73ffffffffffffffffffffffffffffffffffffffff841681526bffffffffffffffffffffffff83166020820152606060408201526000612d076060830184611f2f565b95945050505050565b60008251612d22818460208701611f0b565b919091019291505056fea164736f6c6343000813000a", } var AutomationRegistrarABI = AutomationRegistrarMetaData.ABI 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 461b083fbfb..a8dae2092cb 100644 --- a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -8,7 +8,7 @@ automation_compatible_utils: ../../contracts/solc/v0.8.19/AutomationCompatibleUt automation_consumer_benchmark: ../../contracts/solc/v0.8.16/AutomationConsumerBenchmark/AutomationConsumerBenchmark.abi ../../contracts/solc/v0.8.16/AutomationConsumerBenchmark/AutomationConsumerBenchmark.bin f52c76f1aaed4be541d82d97189d70f5aa027fc9838037dd7a7d21910c8c488e automation_forwarder_logic: ../../contracts/solc/v0.8.16/AutomationForwarderLogic/AutomationForwarderLogic.abi ../../contracts/solc/v0.8.16/AutomationForwarderLogic/AutomationForwarderLogic.bin 15ae0c367297955fdab4b552dbb10e1f2be80a8fde0efec4a4d398693e9d72b5 automation_registrar_wrapper2_1: ../../contracts/solc/v0.8.16/AutomationRegistrar2_1/AutomationRegistrar2_1.abi ../../contracts/solc/v0.8.16/AutomationRegistrar2_1/AutomationRegistrar2_1.bin eb06d853aab39d3196c593b03e555851cbe8386e0fe54a74c2479f62d14b3c42 -automation_registrar_wrapper2_3: ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.bin b42de91c15c7453d8262124e20594819d64a3f23bef8e6db66fa5180d18a8454 +automation_registrar_wrapper2_3: ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.bin 4d8c1fae4c8bf59ad996a1ac00f2131158ac1d96c3039c2e7deaa502f0317719 automation_registry_logic_a_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_2/AutomationRegistryLogicA2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_2/AutomationRegistryLogicA2_2.bin 2f267fb8467a15c587ce4586ac56069f7229344ad3936430d7c7624c0528a171 automation_registry_logic_a_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.bin 1163ecd34c575cb17ffbc2f88fa175816f36982e91992d940ed435d306b3418c automation_registry_logic_b_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_2/AutomationRegistryLogicB2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_2/AutomationRegistryLogicB2_2.bin a6d33dfbbfb0ff253eb59a51f4f6d6d4c22ea5ec95aae52d25d49a312b37a22f From 365c38be8b589d5ffa0b21755dcb40e2e4205652 Mon Sep 17 00:00:00 2001 From: Christopher Dimitri Sastropranoto Date: Thu, 25 Apr 2024 23:33:57 +0700 Subject: [PATCH 16/34] Add functions to add a node operator (#12906) * add functions to add node operator * update gethwrapper --- .changeset/two-countries-lay.md | 5 + contracts/.changeset/tender-jokes-do.md | 5 + .../src/v0.8/keystone/CapabilityRegistry.sol | 72 +++++- .../src/v0.8/keystone/test/BaseTest.t.sol | 22 ++ .../keystone/test/CapabilityRegistry.t.sol | 21 -- ...CapabilityRegistry_AddCapabilityTest.t.sol | 17 ++ ...abilityRegistry_AddNodeOperatorsTest.t.sol | 41 ++++ .../src/v0.8/keystone/test/Constants.t.sol | 13 ++ .../keystone_capability_registry.go | 210 ++++++++++++++++-- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 10 files changed, 361 insertions(+), 47 deletions(-) create mode 100644 .changeset/two-countries-lay.md create mode 100644 contracts/.changeset/tender-jokes-do.md create mode 100644 contracts/src/v0.8/keystone/test/BaseTest.t.sol delete mode 100644 contracts/src/v0.8/keystone/test/CapabilityRegistry.t.sol create mode 100644 contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol create mode 100644 contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodeOperatorsTest.t.sol create mode 100644 contracts/src/v0.8/keystone/test/Constants.t.sol diff --git a/.changeset/two-countries-lay.md b/.changeset/two-countries-lay.md new file mode 100644 index 00000000000..f3d78e6a2e6 --- /dev/null +++ b/.changeset/two-countries-lay.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +update keystone gethwrapper #internal diff --git a/contracts/.changeset/tender-jokes-do.md b/contracts/.changeset/tender-jokes-do.md new file mode 100644 index 00000000000..5500fe0ca00 --- /dev/null +++ b/contracts/.changeset/tender-jokes-do.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +Implement function to add node operators to the capability registry' diff --git a/contracts/src/v0.8/keystone/CapabilityRegistry.sol b/contracts/src/v0.8/keystone/CapabilityRegistry.sol index 7c870bed7fb..ad452f1606b 100644 --- a/contracts/src/v0.8/keystone/CapabilityRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilityRegistry.sol @@ -4,25 +4,73 @@ pragma solidity ^0.8.0; import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol"; import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; -struct Capability { - // Capability type, e.g. "data-streams-reports" - // bytes32(string); validation regex: ^[a-z0-9_\-:]{1,32}$ - // Not "type" because that's a reserved keyword in Solidity. - bytes32 capabilityType; - // Semver, e.g., "1.2.3" - // bytes32(string); must be valid Semver + max 32 characters. - bytes32 version; -} - contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { - mapping(bytes32 => Capability) private s_capabilities; + struct NodeOperator { + /// @notice The address of the admin that can manage a node + /// operator + address admin; + /// @notice Human readable name of a Node Operator managing the node + string name; + } + + struct Capability { + // Capability type, e.g. "data-streams-reports" + // bytes32(string); validation regex: ^[a-z0-9_\-:]{1,32}$ + // Not "type" because that's a reserved keyword in Solidity. + bytes32 capabilityType; + // Semver, e.g., "1.2.3" + // bytes32(string); must be valid Semver + max 32 characters. + bytes32 version; + } + + /// @notice This error is thrown when trying to set a node operator's + /// admin address to the zero address + error InvalidNodeOperatorAdmin(); + + /// @notice This event is emitted when a new node operator is added + /// @param nodeOperatorId The ID of the newly added node operator + /// @param admin The address of the admin that can manage the node + /// operator + /// @param name The human readable name of the node operator + event NodeOperatorAdded(uint256 nodeOperatorId, address indexed admin, string name); + /// @notice This event is emitted when a new capability is added + /// @param capabilityId The ID of the newly added capability event CapabilityAdded(bytes32 indexed capabilityId); + mapping(bytes32 => Capability) private s_capabilities; + + /// @notice Mapping of node operators + mapping(uint256 nodeOperatorId => NodeOperator) private s_nodeOperators; + + /// @notice The latest node operator ID + /// @dev No getter for this as this is an implementation detail + uint256 private s_nodeOperatorId; + function typeAndVersion() external pure override returns (string memory) { return "CapabilityRegistry 1.0.0"; } + /// @notice Adds a list of node operators + /// @param nodeOperators List of node operators to add + function addNodeOperators(NodeOperator[] calldata nodeOperators) external onlyOwner { + for (uint256 i; i < nodeOperators.length; ++i) { + NodeOperator memory nodeOperator = nodeOperators[i]; + if (nodeOperator.admin == address(0)) revert InvalidNodeOperatorAdmin(); + uint256 nodeOperatorId = s_nodeOperatorId; + s_nodeOperators[nodeOperatorId] = NodeOperator({admin: nodeOperator.admin, name: nodeOperator.name}); + ++s_nodeOperatorId; + emit NodeOperatorAdded(nodeOperatorId, nodeOperator.admin, nodeOperator.name); + } + } + + /// @notice Gets a node operator's data + /// @param nodeOperatorId The ID of the node operator to query for + /// @return NodeOperator The node operator data + function getNodeOperator(uint256 nodeOperatorId) external view returns (NodeOperator memory) { + return s_nodeOperators[nodeOperatorId]; + } + function addCapability(Capability calldata capability) external onlyOwner { bytes32 capabilityId = getCapabilityID(capability.capabilityType, capability.version); s_capabilities[capabilityId] = capability; @@ -34,7 +82,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { } /// @notice This functions returns a Capability ID packed into a bytes32 for cheaper access - /// @return A unique identifier for the capability + /// @return bytes32 A unique identifier for the capability function getCapabilityID(bytes32 capabilityType, bytes32 version) public pure returns (bytes32) { return keccak256(abi.encodePacked(capabilityType, version)); } diff --git a/contracts/src/v0.8/keystone/test/BaseTest.t.sol b/contracts/src/v0.8/keystone/test/BaseTest.t.sol new file mode 100644 index 00000000000..5c4b4c91809 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/BaseTest.t.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {Test} from "forge-std/Test.sol"; +import {Constants} from "./Constants.t.sol"; +import {CapabilityRegistry} from "../CapabilityRegistry.sol"; + +contract BaseTest is Test, Constants { + CapabilityRegistry internal s_capabilityRegistry; + + function setUp() public virtual { + vm.startPrank(ADMIN); + s_capabilityRegistry = new CapabilityRegistry(); + } + + function _getNodeOperators() internal view returns (CapabilityRegistry.NodeOperator[] memory) { + CapabilityRegistry.NodeOperator[] memory nodeOperators = new CapabilityRegistry.NodeOperator[](2); + nodeOperators[0] = CapabilityRegistry.NodeOperator({admin: NODE_OPERATOR_ONE_ADMIN, name: NODE_OPERATOR_ONE_NAME}); + nodeOperators[1] = CapabilityRegistry.NodeOperator({admin: NODE_OPERATOR_TWO_ADMIN, name: NODE_OPERATOR_TWO_NAME}); + return nodeOperators; + } +} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry.t.sol deleted file mode 100644 index f5d539d8e34..00000000000 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry.t.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {Test} from "forge-std/Test.sol"; -import {Capability, CapabilityRegistry} from "../CapabilityRegistry.sol"; - -contract CapabilityRegistryTest is Test { - function setUp() public virtual {} - - function testAddCapability() public { - CapabilityRegistry capabilityRegistry = new CapabilityRegistry(); - - capabilityRegistry.addCapability(Capability("data-streams-reports", "1.0.0")); - - bytes32 capabilityId = capabilityRegistry.getCapabilityID(bytes32("data-streams-reports"), bytes32("1.0.0")); - Capability memory capability = capabilityRegistry.getCapability(capabilityId); - - assertEq(capability.capabilityType, "data-streams-reports"); - assertEq(capability.version, "1.0.0"); - } -} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol new file mode 100644 index 00000000000..6fbdc43a2c7 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilityRegistry} from "../CapabilityRegistry.sol"; + +contract CapabilityRegistry_AddCapabilityTest is BaseTest { + function test_AddCapability() public { + s_capabilityRegistry.addCapability(CapabilityRegistry.Capability("data-streams-reports", "1.0.0")); + + bytes32 capabilityId = s_capabilityRegistry.getCapabilityID(bytes32("data-streams-reports"), bytes32("1.0.0")); + CapabilityRegistry.Capability memory capability = s_capabilityRegistry.getCapability(capabilityId); + + assertEq(capability.capabilityType, "data-streams-reports"); + assertEq(capability.version, "1.0.0"); + } +} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodeOperatorsTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodeOperatorsTest.t.sol new file mode 100644 index 00000000000..388c3ca9cdd --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodeOperatorsTest.t.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilityRegistry} from "../CapabilityRegistry.sol"; + +contract CapabilityRegistry_AddNodeOperatorsTest is BaseTest { + event NodeOperatorAdded(uint256 nodeOperatorId, address indexed admin, string name); + + function test_RevertWhen_CalledByNonAdmin() public { + changePrank(STRANGER); + vm.expectRevert("Only callable by owner"); + s_capabilityRegistry.addNodeOperators(_getNodeOperators()); + } + + function test_RevertWhen_NodeOperatorAdminAddressZero() public { + changePrank(ADMIN); + CapabilityRegistry.NodeOperator[] memory nodeOperators = _getNodeOperators(); + nodeOperators[0].admin = address(0); + vm.expectRevert(CapabilityRegistry.InvalidNodeOperatorAdmin.selector); + s_capabilityRegistry.addNodeOperators(nodeOperators); + } + + function test_AddNodeOperators() public { + changePrank(ADMIN); + + vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); + emit NodeOperatorAdded(0, NODE_OPERATOR_ONE_ADMIN, NODE_OPERATOR_ONE_NAME); + vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); + emit NodeOperatorAdded(1, NODE_OPERATOR_TWO_ADMIN, NODE_OPERATOR_TWO_NAME); + s_capabilityRegistry.addNodeOperators(_getNodeOperators()); + + CapabilityRegistry.NodeOperator memory nodeOperatorOne = s_capabilityRegistry.getNodeOperator(0); + assertEq(nodeOperatorOne.admin, NODE_OPERATOR_ONE_ADMIN); + assertEq(nodeOperatorOne.name, NODE_OPERATOR_ONE_NAME); + + CapabilityRegistry.NodeOperator memory nodeOperatorTwo = s_capabilityRegistry.getNodeOperator(1); + assertEq(nodeOperatorTwo.admin, NODE_OPERATOR_TWO_ADMIN); + assertEq(nodeOperatorTwo.name, NODE_OPERATOR_TWO_NAME); + } +} diff --git a/contracts/src/v0.8/keystone/test/Constants.t.sol b/contracts/src/v0.8/keystone/test/Constants.t.sol new file mode 100644 index 00000000000..b7eb85debb1 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/Constants.t.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {Test} from "forge-std/Test.sol"; + +contract Constants { + address internal ADMIN = address(1); + address internal STRANGER = address(2); + address internal NODE_OPERATOR_ONE_ADMIN = address(3); + string internal NODE_OPERATOR_ONE_NAME = "node-operator-one"; + address internal NODE_OPERATOR_TWO_ADMIN = address(4); + string internal NODE_OPERATOR_TWO_NAME = "node-operator-two"; +} diff --git a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go index 45ae103ac56..ef8b252b924 100644 --- a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go +++ b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go @@ -30,14 +30,19 @@ var ( _ = abi.ConvertType ) -type Capability struct { +type CapabilityRegistryCapability struct { CapabilityType [32]byte Version [32]byte } +type CapabilityRegistryNodeOperator struct { + Admin common.Address + Name string +} + var CapabilityRegistryMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"internalType\":\"structCapability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"internalType\":\"structCapability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6105e5806101576000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806379ba50971161005b57806379ba5097146101275780638da5cb5b1461012f5780639cb7c5f414610157578063f2fde38b146101be57600080fd5b8063181f5a7714610082578063229111f5146100ca5780636e5f286914610112575b600080fd5b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516100c191906104dc565b60405180910390f35b6101046100d8366004610548565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b6040519081526020016100c1565b61012561012036600461056a565b6101d1565b005b61012561024e565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100c1565b6101a3610165366004610582565b604080518082019091526000808252602082015250600090815260026020908152604091829020825180840190935280548352600101549082015290565b604080518251815260209283015192810192909252016100c1565b6101256101cc36600461059b565b610350565b6101d9610364565b60408051823560208083018290528085013583850181905284518085038601815260609094018086528451948301949094206000818152600290935294822092835560019092019190915582917f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff069190a25050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146102d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610358610364565b610361816103e7565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146103e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102cb565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610466576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102cb565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208083528351808285015260005b81811015610509578581018301518582016040015282016104ed565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6000806040838503121561055b57600080fd5b50508035926020909101359150565b60006040828403121561057c57600080fd5b50919050565b60006020828403121561059457600080fd5b5035919050565b6000602082840312156105ad57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146105d157600080fd5b939250505056fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b610d9e806101576000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c80636e5f2869116100765780638da5cb5b1161005b5780638da5cb5b146101885780639cb7c5f4146101b0578063f2fde38b1461021757600080fd5b80636e5f28691461016d57806379ba50971461018057600080fd5b8063181f5a77146100a8578063229111f5146100f0578063398f37731461013857806365c14dc71461014d575b600080fd5b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516100e7919061081d565b60405180910390f35b61012a6100fe366004610837565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b6040519081526020016100e7565b61014b610146366004610859565b61022a565b005b61016061015b3660046108ce565b6103c8565b6040516100e791906108e7565b61014b61017b36600461092a565b6104ae565b61014b61052b565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e7565b6101fc6101be3660046108ce565b604080518082019091526000808252602082015250600090815260026020908152604091829020825180840190935280548352600101549082015290565b604080518251815260209283015192810192909252016100e7565b61014b61022536600461096b565b61062d565b610232610641565b60005b818110156103c357600083838381811061025157610251610986565b905060200281019061026391906109b5565b61026c90610a9a565b805190915073ffffffffffffffffffffffffffffffffffffffff166102bd576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600454604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526003909252939020825181547fffffffffffffffffffffffff0000000000000000000000000000000000000000169216919091178155915190919060018201906103409082610bff565b5090505060046000815461035390610d19565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b916103a891859190610d78565b60405180910390a25050806103bc90610d19565b9050610235565b505050565b6040805180820190915260008152606060208201526000828152600360209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff168352600181018054919284019161042590610b64565b80601f016020809104026020016040519081016040528092919081815260200182805461045190610b64565b801561049e5780601f106104735761010080835404028352916020019161049e565b820191906000526020600020905b81548152906001019060200180831161048157829003601f168201915b5050505050815250509050919050565b6104b6610641565b60408051823560208083018290528085013583850181905284518085038601815260609094018086528451948301949094206000818152600290935294822092835560019092019190915582917f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff069190a25050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146105b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610635610641565b61063e816106c4565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016105a8565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610743576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016105a8565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000815180845260005b818110156107df576020818501810151868301820152016107c3565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061083060208301846107b9565b9392505050565b6000806040838503121561084a57600080fd5b50508035926020909101359150565b6000806020838503121561086c57600080fd5b823567ffffffffffffffff8082111561088457600080fd5b818501915085601f83011261089857600080fd5b8135818111156108a757600080fd5b8660208260051b85010111156108bc57600080fd5b60209290920196919550909350505050565b6000602082840312156108e057600080fd5b5035919050565b6020815273ffffffffffffffffffffffffffffffffffffffff82511660208201526000602083015160408084015261092260608401826107b9565b949350505050565b60006040828403121561093c57600080fd5b50919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461096657600080fd5b919050565b60006020828403121561097d57600080fd5b61083082610942565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126109e957600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610a4557610a456109f3565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610a9257610a926109f3565b604052919050565b600060408236031215610aac57600080fd5b610ab4610a22565b610abd83610942565b815260208084013567ffffffffffffffff80821115610adb57600080fd5b9085019036601f830112610aee57600080fd5b813581811115610b0057610b006109f3565b610b30847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610a4b565b91508082523684828501011115610b4657600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c90821680610b7857607f821691505b60208210810361093c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b601f8211156103c357600081815260208120601f850160051c81016020861015610bd85750805b601f850160051c820191505b81811015610bf757828155600101610be4565b505050505050565b815167ffffffffffffffff811115610c1957610c196109f3565b610c2d81610c278454610b64565b84610bb1565b602080601f831160018114610c805760008415610c4a5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610bf7565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015610ccd57888601518255948401946001909101908401610cae565b5085821015610d0957878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610d71577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b82815260406020820152600061092260408301846107b956fea164736f6c6343000813000a", } var CapabilityRegistryABI = CapabilityRegistryMetaData.ABI @@ -176,25 +181,25 @@ func (_CapabilityRegistry *CapabilityRegistryTransactorRaw) Transact(opts *bind. return _CapabilityRegistry.Contract.contract.Transact(opts, method, params...) } -func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (Capability, error) { +func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (CapabilityRegistryCapability, error) { var out []interface{} err := _CapabilityRegistry.contract.Call(opts, &out, "getCapability", capabilityID) if err != nil { - return *new(Capability), err + return *new(CapabilityRegistryCapability), err } - out0 := *abi.ConvertType(out[0], new(Capability)).(*Capability) + out0 := *abi.ConvertType(out[0], new(CapabilityRegistryCapability)).(*CapabilityRegistryCapability) return out0, err } -func (_CapabilityRegistry *CapabilityRegistrySession) GetCapability(capabilityID [32]byte) (Capability, error) { +func (_CapabilityRegistry *CapabilityRegistrySession) GetCapability(capabilityID [32]byte) (CapabilityRegistryCapability, error) { return _CapabilityRegistry.Contract.GetCapability(&_CapabilityRegistry.CallOpts, capabilityID) } -func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapability(capabilityID [32]byte) (Capability, error) { +func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapability(capabilityID [32]byte) (CapabilityRegistryCapability, error) { return _CapabilityRegistry.Contract.GetCapability(&_CapabilityRegistry.CallOpts, capabilityID) } @@ -220,6 +225,28 @@ func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapabilityID(capa return _CapabilityRegistry.Contract.GetCapabilityID(&_CapabilityRegistry.CallOpts, capabilityType, version) } +func (_CapabilityRegistry *CapabilityRegistryCaller) GetNodeOperator(opts *bind.CallOpts, nodeOperatorId *big.Int) (CapabilityRegistryNodeOperator, error) { + var out []interface{} + err := _CapabilityRegistry.contract.Call(opts, &out, "getNodeOperator", nodeOperatorId) + + if err != nil { + return *new(CapabilityRegistryNodeOperator), err + } + + out0 := *abi.ConvertType(out[0], new(CapabilityRegistryNodeOperator)).(*CapabilityRegistryNodeOperator) + + return out0, err + +} + +func (_CapabilityRegistry *CapabilityRegistrySession) GetNodeOperator(nodeOperatorId *big.Int) (CapabilityRegistryNodeOperator, error) { + return _CapabilityRegistry.Contract.GetNodeOperator(&_CapabilityRegistry.CallOpts, nodeOperatorId) +} + +func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetNodeOperator(nodeOperatorId *big.Int) (CapabilityRegistryNodeOperator, error) { + return _CapabilityRegistry.Contract.GetNodeOperator(&_CapabilityRegistry.CallOpts, nodeOperatorId) +} + func (_CapabilityRegistry *CapabilityRegistryCaller) Owner(opts *bind.CallOpts) (common.Address, error) { var out []interface{} err := _CapabilityRegistry.contract.Call(opts, &out, "owner") @@ -276,18 +303,30 @@ func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AcceptOwnership( return _CapabilityRegistry.Contract.AcceptOwnership(&_CapabilityRegistry.TransactOpts) } -func (_CapabilityRegistry *CapabilityRegistryTransactor) AddCapability(opts *bind.TransactOpts, capability Capability) (*types.Transaction, error) { +func (_CapabilityRegistry *CapabilityRegistryTransactor) AddCapability(opts *bind.TransactOpts, capability CapabilityRegistryCapability) (*types.Transaction, error) { return _CapabilityRegistry.contract.Transact(opts, "addCapability", capability) } -func (_CapabilityRegistry *CapabilityRegistrySession) AddCapability(capability Capability) (*types.Transaction, error) { +func (_CapabilityRegistry *CapabilityRegistrySession) AddCapability(capability CapabilityRegistryCapability) (*types.Transaction, error) { return _CapabilityRegistry.Contract.AddCapability(&_CapabilityRegistry.TransactOpts, capability) } -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddCapability(capability Capability) (*types.Transaction, error) { +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddCapability(capability CapabilityRegistryCapability) (*types.Transaction, error) { return _CapabilityRegistry.Contract.AddCapability(&_CapabilityRegistry.TransactOpts, capability) } +func (_CapabilityRegistry *CapabilityRegistryTransactor) AddNodeOperators(opts *bind.TransactOpts, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilityRegistry.contract.Transact(opts, "addNodeOperators", nodeOperators) +} + +func (_CapabilityRegistry *CapabilityRegistrySession) AddNodeOperators(nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.AddNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperators) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddNodeOperators(nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.AddNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperators) +} + func (_CapabilityRegistry *CapabilityRegistryTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { return _CapabilityRegistry.contract.Transact(opts, "transferOwnership", to) } @@ -427,6 +466,135 @@ func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseCapabilityAdded(log return event, nil } +type CapabilityRegistryNodeOperatorAddedIterator struct { + Event *CapabilityRegistryNodeOperatorAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilityRegistryNodeOperatorAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryNodeOperatorAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryNodeOperatorAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilityRegistryNodeOperatorAddedIterator) Error() error { + return it.fail +} + +func (it *CapabilityRegistryNodeOperatorAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilityRegistryNodeOperatorAdded struct { + NodeOperatorId *big.Int + Admin common.Address + Name string + Raw types.Log +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterNodeOperatorAdded(opts *bind.FilterOpts, admin []common.Address) (*CapabilityRegistryNodeOperatorAddedIterator, error) { + + var adminRule []interface{} + for _, adminItem := range admin { + adminRule = append(adminRule, adminItem) + } + + logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "NodeOperatorAdded", adminRule) + if err != nil { + return nil, err + } + return &CapabilityRegistryNodeOperatorAddedIterator{contract: _CapabilityRegistry.contract, event: "NodeOperatorAdded", logs: logs, sub: sub}, nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchNodeOperatorAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorAdded, admin []common.Address) (event.Subscription, error) { + + var adminRule []interface{} + for _, adminItem := range admin { + adminRule = append(adminRule, adminItem) + } + + logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "NodeOperatorAdded", adminRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilityRegistryNodeOperatorAdded) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeOperatorAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeOperatorAdded(log types.Log) (*CapabilityRegistryNodeOperatorAdded, error) { + event := new(CapabilityRegistryNodeOperatorAdded) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeOperatorAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type CapabilityRegistryOwnershipTransferRequestedIterator struct { Event *CapabilityRegistryOwnershipTransferRequested @@ -703,6 +871,8 @@ func (_CapabilityRegistry *CapabilityRegistry) ParseLog(log types.Log) (generate switch log.Topics[0] { case _CapabilityRegistry.abi.Events["CapabilityAdded"].ID: return _CapabilityRegistry.ParseCapabilityAdded(log) + case _CapabilityRegistry.abi.Events["NodeOperatorAdded"].ID: + return _CapabilityRegistry.ParseNodeOperatorAdded(log) case _CapabilityRegistry.abi.Events["OwnershipTransferRequested"].ID: return _CapabilityRegistry.ParseOwnershipTransferRequested(log) case _CapabilityRegistry.abi.Events["OwnershipTransferred"].ID: @@ -717,6 +887,10 @@ func (CapabilityRegistryCapabilityAdded) Topic() common.Hash { return common.HexToHash("0x65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff06") } +func (CapabilityRegistryNodeOperatorAdded) Topic() common.Hash { + return common.HexToHash("0xda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b") +} + func (CapabilityRegistryOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } @@ -730,17 +904,21 @@ func (_CapabilityRegistry *CapabilityRegistry) Address() common.Address { } type CapabilityRegistryInterface interface { - GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (Capability, error) + GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (CapabilityRegistryCapability, error) GetCapabilityID(opts *bind.CallOpts, capabilityType [32]byte, version [32]byte) ([32]byte, error) + GetNodeOperator(opts *bind.CallOpts, nodeOperatorId *big.Int) (CapabilityRegistryNodeOperator, error) + Owner(opts *bind.CallOpts) (common.Address, error) TypeAndVersion(opts *bind.CallOpts) (string, error) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - AddCapability(opts *bind.TransactOpts, capability Capability) (*types.Transaction, error) + AddCapability(opts *bind.TransactOpts, capability CapabilityRegistryCapability) (*types.Transaction, error) + + AddNodeOperators(opts *bind.TransactOpts, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) @@ -750,6 +928,12 @@ type CapabilityRegistryInterface interface { ParseCapabilityAdded(log types.Log) (*CapabilityRegistryCapabilityAdded, error) + FilterNodeOperatorAdded(opts *bind.FilterOpts, admin []common.Address) (*CapabilityRegistryNodeOperatorAddedIterator, error) + + WatchNodeOperatorAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorAdded, admin []common.Address) (event.Subscription, error) + + ParseNodeOperatorAdded(log types.Log) (*CapabilityRegistryNodeOperatorAdded, error) + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilityRegistryOwnershipTransferRequestedIterator, error) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 98fd35e188b..836eb3e68b7 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,4 @@ GETH_VERSION: 1.13.8 forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin b4c900aae9e022f01abbac7993d41f93912247613ac6270b0c4da4ef6f2016e3 -keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin fbaf8eceb929494bdfe0028921a0742da525cb4ec1b6d57a1382eda46fa32c64 +keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin 579334dfcb59da4221823735dc815116745b488ddde327199367e04457aac808 ocr3_capability: ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin 9dcbdf55bd5729ba266148da3f17733eb592c871c2108ccca546618628fd9ad2 From fa5b22773e52744d3abab1a05cd12ecc2e103d88 Mon Sep 17 00:00:00 2001 From: Vyzaldy Sanchez Date: Thu, 25 Apr 2024 13:16:55 -0400 Subject: [PATCH 17/34] Add `onchainSigningStrategy` job spec field support (#12909) * Adds `onchainSigningStrategy` job spec field support * Makes changeset internal * Fixes typo and remove unnecessary logs * Stores `onchain_signing_strategy` values in the DB * Fixes test error --- .changeset/olive-knives-happen.md | 5 + core/services/job/job_orm_test.go | 5 + core/services/job/models.go | 1 + core/services/job/models_test.go | 7 + core/services/job/orm.go | 4 +- core/services/job/testdata/compact.toml | 7 + core/services/job/testdata/pretty.toml | 7 + core/services/ocr2/database_test.go | 4 +- core/services/ocr2/delegate.go | 8 + core/services/ocr2/validate/validate.go | 48 +++++ core/services/ocr2/validate/validate_test.go | 169 ++++++++++++++++++ ...4_generic_plugin_multichain_keybundle_.sql | 11 ++ 12 files changed, 272 insertions(+), 4 deletions(-) create mode 100644 .changeset/olive-knives-happen.md create mode 100644 core/store/migrate/migrations/0234_generic_plugin_multichain_keybundle_.sql diff --git a/.changeset/olive-knives-happen.md b/.changeset/olive-knives-happen.md new file mode 100644 index 00000000000..7f522c96ff1 --- /dev/null +++ b/.changeset/olive-knives-happen.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal Generic Plugin `onchainSigningStrategy` support diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index f07b68d9987..3c7d5a7afa5 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -66,6 +66,11 @@ observationSource = """ chainID = 1 fromBlock = 1000 +[onchainSigningStrategy] +strategyName = 'single-chain' +[onchainSigningStrategy.config] +publicKey = '8fa807463ad73f9ee855cfd60ba406dcf98a2855b3dd8af613107b0f6890a707' + [pluginConfig] serverURL = 'wss://localhost:8080' serverPubKey = '8fa807463ad73f9ee855cfd60ba406dcf98a2855b3dd8af613107b0f6890a707' diff --git a/core/services/job/models.go b/core/services/job/models.go index 0c6390b3dbf..3d510efa0d2 100644 --- a/core/services/job/models.go +++ b/core/services/job/models.go @@ -362,6 +362,7 @@ type OCR2OracleSpec struct { BlockchainTimeout models.Interval `toml:"blockchainTimeout"` ContractConfigTrackerPollInterval models.Interval `toml:"contractConfigTrackerPollInterval"` ContractConfigConfirmations uint16 `toml:"contractConfigConfirmations"` + OnchainSigningStrategy JSONConfig `toml:"onchainSigningStrategy"` PluginConfig JSONConfig `toml:"pluginConfig"` PluginType types.OCR2PluginType `toml:"pluginType"` CreatedAt time.Time `toml:"-"` diff --git a/core/services/job/models_test.go b/core/services/job/models_test.go index 4d10fbb43c4..c177b3b81e1 100644 --- a/core/services/job/models_test.go +++ b/core/services/job/models_test.go @@ -219,6 +219,13 @@ func TestOCR2OracleSpec(t *testing.T) { }, }, }, + OnchainSigningStrategy: map[string]interface{}{ + "strategyName": "single-chain", + "config": map[string]interface{}{ + "evm": "", + "publicKey": "0xdeadbeef", + }, + }, PluginConfig: map[string]interface{}{"juelsPerFeeCoinSource": ` // data source 1 ds1 [type=bridge name="%s"]; ds1_parse [type=jsonparse path="data"]; diff --git a/core/services/job/orm.go b/core/services/job/orm.go index 2b2f73396dc..d87b0204263 100644 --- a/core/services/job/orm.go +++ b/core/services/job/orm.go @@ -461,10 +461,10 @@ func (o *orm) insertOCROracleSpec(ctx context.Context, spec *OCROracleSpec) (spe } func (o *orm) insertOCR2OracleSpec(ctx context.Context, spec *OCR2OracleSpec) (specID int32, err error) { - return o.prepareQuerySpecID(ctx, `INSERT INTO ocr2_oracle_specs (contract_id, feed_id, relay, relay_config, plugin_type, plugin_config, p2pv2_bootstrappers, ocr_key_bundle_id, transmitter_id, + return o.prepareQuerySpecID(ctx, `INSERT INTO ocr2_oracle_specs (contract_id, feed_id, relay, relay_config, plugin_type, plugin_config, onchain_signing_strategy, p2pv2_bootstrappers, ocr_key_bundle_id, transmitter_id, blockchain_timeout, contract_config_tracker_poll_interval, contract_config_confirmations, created_at, updated_at) - VALUES (:contract_id, :feed_id, :relay, :relay_config, :plugin_type, :plugin_config, :p2pv2_bootstrappers, :ocr_key_bundle_id, :transmitter_id, + VALUES (:contract_id, :feed_id, :relay, :relay_config, :plugin_type, :plugin_config, :onchain_signing_strategy, :p2pv2_bootstrappers, :ocr_key_bundle_id, :transmitter_id, :blockchain_timeout, :contract_config_tracker_poll_interval, :contract_config_confirmations, NOW(), NOW()) RETURNING id;`, spec) diff --git a/core/services/job/testdata/compact.toml b/core/services/job/testdata/compact.toml index 9f0f54027d2..5517c69ffa1 100644 --- a/core/services/job/testdata/compact.toml +++ b/core/services/job/testdata/compact.toml @@ -30,5 +30,12 @@ LatestTransmissionDetails = "{\n \"chainSpecificName\": \"latestTransmissionDet [relayConfig.codec.configs.MedianReport] typeABI = "[\n {\n \"Name\": \"Timestamp\",\n \"Type\": \"uint32\"\n },\n {\n \"Name\": \"Observers\",\n \"Type\": \"bytes32\"\n },\n {\n \"Name\": \"Observations\",\n \"Type\": \"int192[]\"\n },\n {\n \"Name\": \"JuelsPerFeeCoin\",\n \"Type\": \"int192\"\n }\n]\n" +[onchainSigningStrategy] +strategyName = 'single-chain' + +[onchainSigningStrategy.config] +evm = '' +publicKey = '0xdeadbeef' + [pluginConfig] juelsPerFeeCoinSource = " // data source 1\n ds1 [type=bridge name=\"%s\"];\n ds1_parse [type=jsonparse path=\"data\"];\n ds1_multiply [type=multiply times=2];\n\n // data source 2\n ds2 [type=http method=GET url=\"%s\"];\n ds2_parse [type=jsonparse path=\"data\"];\n ds2_multiply [type=multiply times=2];\n\n ds1 -> ds1_parse -> ds1_multiply -> answer1;\n ds2 -> ds2_parse -> ds2_multiply -> answer1;\n\n answer1 [type=median index=0];\n" diff --git a/core/services/job/testdata/pretty.toml b/core/services/job/testdata/pretty.toml index 88bacff7db2..1bed3efac0d 100644 --- a/core/services/job/testdata/pretty.toml +++ b/core/services/job/testdata/pretty.toml @@ -130,6 +130,13 @@ typeABI = ''' ] ''' +[onchainSigningStrategy] +strategyName = 'single-chain' + +[onchainSigningStrategy.config] +evm = '' +publicKey = '0xdeadbeef' + [pluginConfig] juelsPerFeeCoinSource = """ // data source 1 diff --git a/core/services/ocr2/database_test.go b/core/services/ocr2/database_test.go index 3e78249d087..3d3eec22a6d 100644 --- a/core/services/ocr2/database_test.go +++ b/core/services/ocr2/database_test.go @@ -40,9 +40,9 @@ func MustInsertOCROracleSpec(t *testing.T, db *sqlx.DB, transmitterAddress types require.NoError(t, db.Get(&spec, `INSERT INTO ocr2_oracle_specs ( relay, relay_config, contract_id, p2pv2_bootstrappers, ocr_key_bundle_id, monitoring_endpoint, transmitter_id, -blockchain_timeout, contract_config_tracker_poll_interval, contract_config_confirmations, plugin_type, plugin_config, created_at, updated_at) VALUES ( +blockchain_timeout, contract_config_tracker_poll_interval, contract_config_confirmations, plugin_type, plugin_config, onchain_signing_strategy, created_at, updated_at) VALUES ( 'ethereum', '{}', $1, '{}', $2, $3, $4, -0, 0, 0, 'median', $5, NOW(), NOW() +0, 0, 0, 'median', $5, '{}', NOW(), NOW() ) RETURNING *`, cltest.NewEIP55Address().String(), cltest.DefaultOCR2KeyBundleID, "chain.link:1234", transmitterAddress.String(), jsonConfig)) return spec } diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index 6c76b0ff9c9..2e623ab5467 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -27,6 +27,7 @@ import ( ocr2keepers21 "github.com/smartcontractkit/chainlink-automation/pkg/v3/plugin" "github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins/ocr3" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink-vrf/altbn_128" @@ -539,6 +540,13 @@ func (d *Delegate) newServicesGenericPlugin( if err != nil { return nil, err } + // NOTE: we don't need to validate the strategy, since that happens as part of creating the job. + // See: validate/validate.go's `validateSpec`. + onchainSigningStrategy := validate.OCR2OnchainSigningStrategy{} + err = json.Unmarshal(spec.OnchainSigningStrategy.Bytes(), &onchainSigningStrategy) + if err != nil { + return nil, err + } plugEnv := env.NewPlugin(pCfg.PluginName) diff --git a/core/services/ocr2/validate/validate.go b/core/services/ocr2/validate/validate.go index 59f7053de56..9a85d7993a4 100644 --- a/core/services/ocr2/validate/validate.go +++ b/core/services/ocr2/validate/validate.go @@ -16,6 +16,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins" "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/services/job" dkgconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/dkg/config" @@ -172,6 +173,40 @@ func (o *OCR2GenericPluginConfig) UnmarshalJSON(data []byte) error { return nil } +type onchainSigningStrategyInner struct { + StrategyName string `json:"strategyName"` + Config job.JSONConfig `json:"config"` +} + +type OCR2OnchainSigningStrategy struct { + onchainSigningStrategyInner +} + +func (o *OCR2OnchainSigningStrategy) UnmarshalJSON(data []byte) error { + err := json.Unmarshal(data, &o.onchainSigningStrategyInner) + if err != nil { + return err + } + + return nil +} + +func (o *OCR2OnchainSigningStrategy) IsMultiChain() bool { + return o.StrategyName == "multi-chain" +} + +func (o *OCR2OnchainSigningStrategy) PublicKey() (string, error) { + pk, ok := o.Config["publicKey"] + if !ok { + return "", nil + } + name, ok := pk.(string) + if !ok { + return "", fmt.Errorf("expected string publicKey value, but got: %T", pk) + } + return name, nil +} + func validateGenericPluginSpec(ctx context.Context, spec *job.OCR2OracleSpec, rc plugins.RegistrarConfig) error { p := OCR2GenericPluginConfig{} err := json.Unmarshal(spec.PluginConfig.Bytes(), &p) @@ -187,6 +222,19 @@ func validateGenericPluginSpec(ctx context.Context, spec *job.OCR2OracleSpec, rc return errors.New("generic config invalid: only OCR version 2 and 3 are supported") } + onchainSigningStrategy := OCR2OnchainSigningStrategy{} + err = json.Unmarshal(spec.OnchainSigningStrategy.Bytes(), &onchainSigningStrategy) + if err != nil { + return err + } + pk, err := onchainSigningStrategy.PublicKey() + if err != nil { + return err + } + if pk == "" { + return errors.New("generic config invalid: must provide public key for the onchain signing strategy") + } + plugEnv := env.NewPlugin(p.PluginName) command := p.Command diff --git a/core/services/ocr2/validate/validate_test.go b/core/services/ocr2/validate/validate_test.go index fad5a36e51f..05881187ba4 100644 --- a/core/services/ocr2/validate/validate_test.go +++ b/core/services/ocr2/validate/validate_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -44,6 +45,11 @@ answer1 [type=median index=0]; """ [relayConfig] chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] juelsPerFeeCoinSource = """ ds1 [type=bridge name=voter_turnout]; @@ -66,6 +72,8 @@ answer1 [type=median index=0]; var pc medianconfig.PluginConfig require.NoError(t, json.Unmarshal(r.PluginConfig.Bytes(), &pc)) require.NoError(t, medianconfig.ValidatePluginConfig(pc)) + var oss validate.OCR2OnchainSigningStrategy + require.NoError(t, json.Unmarshal(r.OnchainSigningStrategy.Bytes(), &oss)) }, }, { @@ -93,6 +101,11 @@ answer1 [type=median index=0]; """ [relayConfig] chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] juelsPerFeeCoinSource = """ ds1 [type=bridge name=voter_turnout]; @@ -133,6 +146,11 @@ answer1 [type=median index=0]; """ [relayConfig] chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] `, assertion: func(t *testing.T, os job.Job, err error) { @@ -152,6 +170,11 @@ p2pPeerID = "12D3KooWHfYFQ8hGttAYbMCevQVESEQhzJAqFZokMVtom8bNxwGq" p2pv2Bootstrappers = [] [relayConfig] chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] `, assertion: func(t *testing.T, os job.Job, err error) { @@ -173,6 +196,11 @@ observationSource = """ """ [relayConfig] chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] `, assertion: func(t *testing.T, os job.Job, err error) { @@ -194,6 +222,11 @@ blah """ [relayConfig] chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] `, assertion: func(t *testing.T, os job.Job, err error) { @@ -216,6 +249,11 @@ blah """ [relayConfig] chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] `, assertion: func(t *testing.T, os job.Job, err error) { @@ -237,6 +275,11 @@ blah """ [relayConfig] chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] `, assertion: func(t *testing.T, os job.Job, err error) { @@ -256,6 +299,11 @@ p2pv2Bootstrappers = [] monitoringEndpoint = "\t/fd\2ff )(*&^%$#@" [relayConfig] chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] `, assertion: func(t *testing.T, os job.Job, err error) { @@ -292,6 +340,11 @@ ds1_multiply [type=multiply times=1.23]; ds1 -> ds1_parse -> ds1_multiply -> answer1; answer1 [type=median index=0]; """ +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] juelsPerFeeCoinSource = """ ds1 [type=bridge name=voter_turnout]; @@ -326,6 +379,11 @@ ds1_multiply [type=multiply times=1.23]; ds1 -> ds1_parse -> ds1_multiply -> answer1; answer1 [type=median index=0]; """ +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] juelsPerFeeCoinSource = """ -> @@ -353,6 +411,11 @@ ds1_multiply [type=multiply times=1.23]; ds1 -> ds1_parse -> ds1_multiply -> answer1; answer1 [type=median index=0]; """ +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" [pluginConfig] juelsPerFeeCoinSource = """ ds1 [type=bridge name=voter_turnout]; @@ -386,6 +449,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] EncryptionPublicKey = "0e86e8cf899ae9a1b43e023bbe8825b103659bb8d6d4e54f6a3cfae7b106069c" SigningPublicKey = "eb62dbd2beb7c1524275a8019022f6ce6a7e86c9e65e3099452a2b96fc2432b1" @@ -415,6 +484,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] EncryptionPublicKey = "frog" SigningPublicKey = "eb62dbd2beb7c1524275a8019022f6ce6a7e86c9e65e3099452a2b96fc2432b1" @@ -446,6 +521,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] EncryptionPublicKey = "0e86e8cf899ae9a1b43e023bbe8825b103659bb8d6d4e54f6a3cfae7b10606" SigningPublicKey = "eb62dbd2beb7c1524275a8019022f6ce6a7e86c9e65e3099452a2b96fc2432b1" @@ -477,6 +558,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] EncryptionPublicKey = "0e86e8cf899ae9a1b43e023bbe8825b103659bb8d6d4e54f6a3cfae7b106069c" SigningPublicKey = "frog" @@ -508,6 +595,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] EncryptionPublicKey = "0e86e8cf899ae9a1b43e023bbe8825b103659bb8d6d4e54f6a3cfae7b106069c" SigningPublicKey = "eb62dbd2beb7c1524275a8019022f6ce6a7e86c9e65e3099452a2b96fc24" @@ -539,6 +632,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] EncryptionPublicKey = "0e86e8cf899ae9a1b43e023bbe8825b103659bb8d6d4e54f6a3cfae7b106069c" SigningPublicKey = "eb62dbd2beb7c1524275a8019022f6ce6a7e86c9e65e3099452a2b96fc2432b1" @@ -570,6 +669,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] EncryptionPublicKey = "0e86e8cf899ae9a1b43e023bbe8825b103659bb8d6d4e54f6a3cfae7b106069c" SigningPublicKey = "eb62dbd2beb7c1524275a8019022f6ce6a7e86c9e65e3099452a2b96fc2432b1" @@ -581,6 +686,46 @@ KeyID = "6f3b82406688b8ddb944c6f2e6d808f014c8fa8d568d639c25019568c require.Contains(t, err.Error(), "validation error for keyID") }, }, + { + name: "Generic public onchain signing strategy with no public key", + toml: ` +type = "offchainreporting2" +pluginType = "plugin" +schemaVersion = 1 +relay = "evm" +contractID = "0x613a38AC1659769640aaE063C651F48E0250454C" +p2pPeerID = "12D3KooWHfYFQ8hGttAYbMCevQVESEQhzJAqFZokMVtom8bNxwGq" +p2pv2Bootstrappers = [ +"12D3KooWHfYFQ8hGttAYbMCevQVESEQhzJAqFZokMVtom8bNxwGq@127.0.0.1:5001", +] +ocrKeyBundleID = "73e8966a78ca09bb912e9565cfb79fbe8a6048fab1f0cf49b18047c3895e0447" +monitoringEndpoint = "chain.link:4321" +transmitterID = "0xF67D0290337bca0847005C7ffD1BC75BA9AAE6e4" +observationTimeout = "10s" +observationSource = """ +ds1 [type=bridge name=voter_turnout]; +ds1_parse [type=jsonparse path="one,two"]; +ds1_multiply [type=multiply times=1.23]; +ds1 -> ds1_parse -> ds1_multiply -> answer1; +answer1 [type=median index=0]; +""" +[relayConfig] +chainID = 1337 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "" +[pluginConfig] +pluginName = "median" +telemetryType = "median" +OCRVersion=2 +`, + assertion: func(t *testing.T, os job.Job, err error) { + require.Error(t, err) + require.Contains(t, err.Error(), "must provide public key for the onchain signing strategy") + }, + }, { name: "Generic plugin config validation - nothing provided", toml: ` @@ -601,6 +746,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] `, assertion: func(t *testing.T, os job.Job, err error) { @@ -627,6 +778,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] PluginName="some random name" `, @@ -655,6 +812,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] PluginName="some random name" OCRVersion=2 @@ -684,6 +847,12 @@ transmitterID = "0x74103Cf8b436465870b26aa9Fa2F62AD62b22E35" [relayConfig] chainID = 4 +[onchainSigningStrategy] +strategyName = "single-chain" +[onchainSigningStrategy.config] +evm = "" +publicKey = "0x1234567890123456789012345678901234567890" + [pluginConfig] PluginName="some random name" OCRVersion=2 diff --git a/core/store/migrate/migrations/0234_generic_plugin_multichain_keybundle_.sql b/core/store/migrate/migrations/0234_generic_plugin_multichain_keybundle_.sql new file mode 100644 index 00000000000..b29ff9de382 --- /dev/null +++ b/core/store/migrate/migrations/0234_generic_plugin_multichain_keybundle_.sql @@ -0,0 +1,11 @@ +-- +goose Up +-- +goose StatementBegin +ALTER TABLE ocr2_oracle_specs + ADD COLUMN onchain_signing_strategy JSONB NOT NULL DEFAULT '{}'; +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +ALTER TABLE ocr2_oracle_specs + DROP COLUMN onchain_signing_strategy; +-- +goose StatementEnd \ No newline at end of file From 7967744ef9ac240cc903d144a3e5ffc09bd06327 Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 25 Apr 2024 14:29:28 -0400 Subject: [PATCH 18/34] Force mercury poll time to 1s (#12771) --- core/services/ocr2/delegate.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index 2e623ab5467..dbde65efe40 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -768,6 +768,11 @@ func (d *Delegate) newServicesMercury( return nil, errors.New("could not coerce PluginProvider to MercuryProvider") } + // HACK: We need fast config switchovers because they create downtime. This + // won't be properly resolved until we implement blue-green deploys: + // https://smartcontract-it.atlassian.net/browse/MERC-3386 + lc.ContractConfigTrackerPollInterval = 1 * time.Second // Mercury requires a fast poll interval, this is the fastest that libocr supports. See: https://github.com/smartcontractkit/offchain-reporting/pull/520 + oracleArgsNoPlugin := libocr2.MercuryOracleArgs{ BinaryNetworkEndpointFactory: d.peerWrapper.Peer2, V2Bootstrappers: bootstrapPeers, From 167782c680b92b1e99ae3e9d1a8b87fd595dd644 Mon Sep 17 00:00:00 2001 From: Lei Date: Thu, 25 Apr 2024 11:57:35 -0700 Subject: [PATCH 19/34] minor improvements on contracts (#12944) --- .changeset/tricky-bats-exist.md | 5 + contracts/.changeset/new-guests-accept.md | 5 + .../dev/v2_3/AutomationRegistrar2_3.sol | 14 +- .../dev/v2_3/AutomationRegistry2_3.sol | 18 +- .../dev/v2_3/AutomationRegistryBase2_3.sol | 52 ++--- .../dev/v2_3/AutomationRegistryLogicA2_3.sol | 1 + .../dev/v2_3/AutomationRegistryLogicC2_3.sol | 7 +- .../automation/AutomationRegistrar2_3.test.ts | 182 ++++++++---------- .../automation_registrar_wrapper2_3.go | 18 +- ...automation_registry_logic_a_wrapper_2_3.go | 2 +- .../automation_registry_wrapper_2_3.go | 2 +- ...rapper-dependency-versions-do-not-edit.txt | 6 +- 12 files changed, 151 insertions(+), 161 deletions(-) create mode 100644 .changeset/tricky-bats-exist.md create mode 100644 contracts/.changeset/new-guests-accept.md diff --git a/.changeset/tricky-bats-exist.md b/.changeset/tricky-bats-exist.md new file mode 100644 index 00000000000..3c748353859 --- /dev/null +++ b/.changeset/tricky-bats-exist.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +minor fixes #bugfix diff --git a/contracts/.changeset/new-guests-accept.md b/contracts/.changeset/new-guests-accept.md new file mode 100644 index 00000000000..080fe17b2bc --- /dev/null +++ b/contracts/.changeset/new-guests-accept.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +minor fixes #bugfix diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistrar2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistrar2_3.sol index 4284ba62f9d..8d4bf17ce91 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistrar2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistrar2_3.sol @@ -81,7 +81,7 @@ contract AutomationRegistrar2_3 is TypeAndVersionInterface, ConfirmedOwner, IERC } /** * @member upkeepContract address to perform upkeep on - * @member amount quantity of LINK upkeep is funded with (specified in wei) + * @member amount quantity of billing token upkeep is funded with (specified in the billing token's decimals) * @member adminAddress address to cancel upkeep and withdraw remaining funds * @member gasLimit amount of gas to provide the target contract when performing upkeep * @member triggerType the type of trigger for the upkeep @@ -204,19 +204,17 @@ contract AutomationRegistrar2_3 is TypeAndVersionInterface, ConfirmedOwner, IERC /** * @dev register upkeep on AutomationRegistry contract and emit RegistrationApproved event * @param requestParams struct of all possible registration parameters - * @param hash the committment of the registration request */ - function approve(RegistrationParams calldata requestParams, bytes32 hash) external onlyOwner { + function approve(RegistrationParams calldata requestParams) external onlyOwner { + bytes32 hash = keccak256(abi.encode(requestParams)); + PendingRequest memory request = s_pendingRequests[hash]; if (request.admin == address(0)) { revert RequestNotFound(); } - bytes32 expectedHash = keccak256(abi.encode(requestParams)); - if (hash != expectedHash) { - revert HashMismatch(); - } + delete s_pendingRequests[hash]; - _approve(requestParams, expectedHash); + _approve(requestParams, hash); } /** diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistry2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistry2_3.sol index 93d3376a4f6..318b382ab32 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistry2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistry2_3.sol @@ -207,13 +207,13 @@ contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chain report.upkeepIds[i], upkeepTransmitInfo[i].upkeep ); - transmitVars.totalPremium += receipt.premiumJuels; - transmitVars.totalReimbursement += receipt.gasReimbursementJuels; + transmitVars.totalPremium += receipt.premiumInJuels; + transmitVars.totalReimbursement += receipt.gasReimbursementInJuels; emit UpkeepPerformed( report.upkeepIds[i], upkeepTransmitInfo[i].performSuccess, - receipt.gasReimbursementJuels + receipt.premiumJuels, // TODO - this is currently the LINK amount, but may change to billing token + receipt.gasReimbursementInJuels + receipt.premiumInJuels, // TODO - this is currently the LINK amount, but may change to billing token upkeepTransmitInfo[i].gasUsed, gasOverhead, report.triggers[i] @@ -320,6 +320,10 @@ contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chain chainModule: onchainConfig.chainModule }); + uint32 previousConfigBlockNumber = s_storage.latestConfigBlockNumber; + uint32 newLatestConfigBlockNumber = uint32(onchainConfig.chainModule.blockNumber()); + uint32 newConfigCount = s_storage.configCount + 1; + s_storage = Storage({ checkGasLimit: onchainConfig.checkGasLimit, maxPerformGas: onchainConfig.maxPerformGas, @@ -330,17 +334,13 @@ contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chain upkeepPrivilegeManager: onchainConfig.upkeepPrivilegeManager, financeAdmin: onchainConfig.financeAdmin, nonce: s_storage.nonce, - configCount: s_storage.configCount, - latestConfigBlockNumber: s_storage.latestConfigBlockNumber + configCount: newConfigCount, + latestConfigBlockNumber: newLatestConfigBlockNumber }); s_fallbackGasPrice = onchainConfig.fallbackGasPrice; s_fallbackLinkPrice = onchainConfig.fallbackLinkPrice; s_fallbackNativePrice = onchainConfig.fallbackNativePrice; - uint32 previousConfigBlockNumber = s_storage.latestConfigBlockNumber; - s_storage.latestConfigBlockNumber = uint32(onchainConfig.chainModule.blockNumber()); - s_storage.configCount += 1; - bytes memory onchainConfigBytes = abi.encode(onchainConfig); s_latestConfigDigest = _configDigestFromConfigData( diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryBase2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryBase2_3.sol index 62c72adffc4..cb90bddf1f9 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryBase2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryBase2_3.sol @@ -41,7 +41,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { uint8 internal constant UPKEEP_VERSION_BASE = 4; // Next block of constants are only used in maxPayment estimation during checkUpkeep simulation - // These values are calibrated using hardhat tests which simulates various cases and verifies that + // These values are calibrated using hardhat tests which simulate various cases and verify that // the variables result in accurate estimation uint256 internal constant REGISTRY_CONDITIONAL_OVERHEAD = 93_000; // Fixed gas overhead for conditional upkeeps uint256 internal constant REGISTRY_LOG_OVERHEAD = 118_000; // Fixed gas overhead for log upkeeps @@ -433,16 +433,16 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { /** * @notice struct containing receipt information about a payment or cost estimation - * @member gasCharge the amount to charge a user for gas spent using the billing token's native decimals - * @member premium the premium charged to the user, shared between all nodes, using the billing token's native decimals - * @member gasReimbursementJuels the amount to reimburse a node for gas spent - * @member premiumJuels the premium paid to NOPs, shared between all nodes + * @member gasChargeInBillingToken the amount to charge a user for gas spent using the billing token's native decimals + * @member premiumInBillingToken the premium charged to the user, shared between all nodes, using the billing token's native decimals + * @member gasReimbursementInJuels the amount to reimburse a node for gas spent + * @member premiumInJuels the premium paid to NOPs, shared between all nodes */ struct PaymentReceipt { - uint96 gasCharge; - uint96 premium; - uint96 gasReimbursementJuels; - uint96 premiumJuels; + uint96 gasChargeInBillingToken; + uint96 premiumInBillingToken; + uint96 gasReimbursementInJuels; + uint96 premiumInJuels; } event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); @@ -683,12 +683,12 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { uint256 gasPaymentHexaicosaUSD = (gasWei * (paymentParams.gasLimit + paymentParams.gasOverhead) + paymentParams.l1CostWei) * paymentParams.nativeUSD; // gasPaymentHexaicosaUSD has an extra 8 zeros because of decimals on nativeUSD feed - // gasCharge is scaled by the billing token's decimals - receipt.gasCharge = SafeCast.toUint96( + // gasChargeInBillingToken is scaled by the billing token's decimals + receipt.gasChargeInBillingToken = SafeCast.toUint96( (gasPaymentHexaicosaUSD * numeratorScalingFactor) / (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor) ); - receipt.gasReimbursementJuels = SafeCast.toUint96(gasPaymentHexaicosaUSD / paymentParams.linkUSD); + receipt.gasReimbursementInJuels = SafeCast.toUint96(gasPaymentHexaicosaUSD / paymentParams.linkUSD); // premium calculation uint256 flatFeeHexaicosaUSD = uint256(paymentParams.billingTokenParams.flatFeeMilliCents) * 1e21; // 1e13 for milliCents to attoUSD and 1e8 for attoUSD to hexaicosaUSD @@ -696,11 +696,11 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { paymentParams.billingTokenParams.gasFeePPB * paymentParams.nativeUSD) / 1e9) + flatFeeHexaicosaUSD; // premium is scaled by the billing token's decimals - receipt.premium = SafeCast.toUint96( + receipt.premiumInBillingToken = SafeCast.toUint96( (premiumHexaicosaUSD * numeratorScalingFactor) / (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor) ); - receipt.premiumJuels = SafeCast.toUint96(premiumHexaicosaUSD / paymentParams.linkUSD); + receipt.premiumInJuels = SafeCast.toUint96(premiumHexaicosaUSD / paymentParams.linkUSD); return receipt; } @@ -764,7 +764,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { }) ); - return receipt.gasCharge + receipt.premium; + return receipt.gasChargeInBillingToken + receipt.premiumInBillingToken; } /** @@ -1002,22 +1002,23 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { // balance is in the token's native decimals uint96 balance = upkeep.balance; // payment is in the token's native decimals - uint96 payment = receipt.gasCharge + receipt.premium; + uint96 payment = receipt.gasChargeInBillingToken + receipt.premiumInBillingToken; // this shouldn't happen, but in rare edge cases, we charge the full balance in case the user // can't cover the amount owed - if (balance < receipt.gasCharge) { + if (balance < receipt.gasChargeInBillingToken) { // if the user can't cover the gas fee, then direct all of the payment to the transmitter and distribute no premium to the DON payment = balance; - receipt.gasReimbursementJuels = SafeCast.toUint96( + receipt.gasReimbursementInJuels = SafeCast.toUint96( (balance * paymentParams.billingTokenParams.priceUSD) / paymentParams.linkUSD ); - receipt.premiumJuels = 0; + receipt.premiumInJuels = 0; } else if (balance < payment) { // if the user can cover the gas fee, but not the premium, then reduce the premium payment = balance; - receipt.premiumJuels = SafeCast.toUint96( - ((balance * paymentParams.billingTokenParams.priceUSD) / paymentParams.linkUSD) - receipt.gasReimbursementJuels + receipt.premiumInJuels = SafeCast.toUint96( + ((balance * paymentParams.billingTokenParams.priceUSD) / paymentParams.linkUSD) - + receipt.gasReimbursementInJuels ); } @@ -1120,13 +1121,12 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { * @notice updates the signers and transmitters lists */ function _updateTransmitters(address[] memory signers, address[] memory transmitters) internal { + uint96 transmittersListLength = uint96(s_transmittersList.length); + uint96 totalPremium = s_hotVars.totalPremium; + // move all pooled payments out of the pool to each transmitter's balance for (uint256 i = 0; i < s_transmittersList.length; i++) { - _updateTransmitterBalanceFromPool( - s_transmittersList[i], - s_hotVars.totalPremium, - uint96(s_transmittersList.length) - ); + _updateTransmitterBalanceFromPool(s_transmittersList[i], totalPremium, transmittersListLength); } // remove any old signer/transmitter addresses diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicA2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicA2_3.sol index 99fc97ce5ce..70ac2c6a38c 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicA2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicA2_3.sol @@ -198,6 +198,7 @@ contract AutomationRegistryLogicA2_3 is AutomationRegistryBase2_3, Chainable { delete s_upkeepOffchainConfig[id]; // nullify existing proposed admin change if an upkeep is being migrated delete s_proposedAdmin[id]; + delete s_upkeepAdmin[id]; s_upkeepIDs.remove(id); emit UpkeepMigrated(id, upkeep.balance, destination); } diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol index 4048227f111..d4565615ad1 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol @@ -161,6 +161,7 @@ contract AutomationRegistryLogicC2_3 is AutomationRegistryBase2_3 { _onlyFinanceAdminAllowed(); if (s_payoutMode == PayoutMode.ON_CHAIN) revert MustSettleOnchain(); + uint96 totalPremium = s_hotVars.totalPremium; uint256 activeTransmittersLength = s_transmittersList.length; uint256 deactivatedTransmittersLength = s_deactivatedTransmitters.length(); uint256 length = activeTransmittersLength + deactivatedTransmittersLength; @@ -171,7 +172,7 @@ contract AutomationRegistryLogicC2_3 is AutomationRegistryBase2_3 { address transmitterAddr = s_transmittersList[i]; uint96 balance = _updateTransmitterBalanceFromPool( transmitterAddr, - s_hotVars.totalPremium, + totalPremium, uint96(activeTransmittersLength) ); @@ -548,7 +549,7 @@ contract AutomationRegistryLogicC2_3 is AutomationRegistryBase2_3 { } /** - * @notice returns the upkeep privilege config + * @notice returns the admin's privilege config */ function getAdminPrivilegeConfig(address admin) external view returns (bytes memory) { return s_adminPrivilegeConfig[admin]; @@ -562,7 +563,7 @@ contract AutomationRegistryLogicC2_3 is AutomationRegistryBase2_3 { } /** - * @notice returns the upkeep's forwarder contract + * @notice returns if the dedupKey exists or not */ function hasDedupKey(bytes32 dedupKey) external view returns (bool) { return s_dedupKeys[dedupKey]; diff --git a/contracts/test/v0.8/automation/AutomationRegistrar2_3.test.ts b/contracts/test/v0.8/automation/AutomationRegistrar2_3.test.ts index 02191dab999..31712e1380b 100644 --- a/contracts/test/v0.8/automation/AutomationRegistrar2_3.test.ts +++ b/contracts/test/v0.8/automation/AutomationRegistrar2_3.test.ts @@ -802,7 +802,6 @@ describe('AutomationRegistrar2_3', () => { }) describe('#approve', () => { - let hash: string let params: RegistrationParams beforeEach(async () => { @@ -834,47 +833,40 @@ describe('AutomationRegistrar2_3', () => { const tx = await linkToken .connect(requestSender) .transferAndCall(registrar.address, amount, abiEncodedBytes) - const receipt = await tx.wait() - hash = receipt.logs[2].topics[1] + await tx.wait() }) it('reverts if not called by the owner', async () => { - const tx = registrar.connect(stranger).approve( - { - name: upkeepName, - encryptedEmail: emptyBytes, - upkeepContract: mock.address, - gasLimit: performGas, - adminAddress: await admin.getAddress(), - checkData: emptyBytes, - triggerType: Trigger.CONDITION, - triggerConfig: trigger, - offchainConfig: emptyBytes, - amount, - billingToken: linkToken.address, - }, - hash, - ) + const tx = registrar.connect(stranger).approve({ + name: upkeepName, + encryptedEmail: emptyBytes, + upkeepContract: mock.address, + gasLimit: performGas, + adminAddress: await admin.getAddress(), + checkData: emptyBytes, + triggerType: Trigger.CONDITION, + triggerConfig: trigger, + offchainConfig: emptyBytes, + amount, + billingToken: linkToken.address, + }) await evmRevert(tx, 'Only callable by owner') }) it('reverts if the hash does not exist', async () => { - const tx = registrar.connect(registrarOwner).approve( - { - name: upkeepName, - encryptedEmail: emptyBytes, - upkeepContract: mock.address, - gasLimit: performGas, - adminAddress: await admin.getAddress(), - checkData: emptyBytes, - triggerType: Trigger.CONDITION, - triggerConfig: trigger, - offchainConfig: emptyBytes, - amount, - billingToken: linkToken.address, - }, - '0x000000000000000000000000322813fd9a801c5507c9de605d63cea4f2ce6c44', - ) + const tx = registrar.connect(registrarOwner).approve({ + name: upkeepName, + encryptedEmail: emptyBytes, + upkeepContract: mock.address, + gasLimit: performGas, + adminAddress: await admin.getAddress(), + checkData: emptyBytes, + triggerType: Trigger.CONDITION, + triggerConfig: trigger, + offchainConfig: emptyBytes, + amount, + billingToken: linkToken.address, + }) await evmRevertCustomError(tx, registrar, errorMsgs.requestNotFound) }) @@ -917,67 +909,58 @@ describe('AutomationRegistrar2_3', () => { for (let i = 0; i < invalidFields.length; i++) { const field = invalidFields[i] const badParams = Object.assign({}, params, field) as RegistrationParams - const tx = registrar.connect(registrarOwner).approve(badParams, hash) + const tx = registrar.connect(registrarOwner).approve(badParams) await expect( tx, `expected ${JSON.stringify(field)} to cause failure, but succeeded`, - ).to.be.revertedWithCustomError(registrar, errorMsgs.hashPayload) + ).to.be.revertedWithCustomError(registrar, errorMsgs.requestNotFound) } }) it('approves an existing registration request', async () => { - const tx = await registrar.connect(registrarOwner).approve( - { - name: upkeepName, - encryptedEmail: emptyBytes, - upkeepContract: mock.address, - gasLimit: performGas, - adminAddress: await admin.getAddress(), - checkData: emptyBytes, - triggerType: Trigger.CONDITION, - triggerConfig: trigger, - offchainConfig, - amount, - billingToken: linkToken.address, - }, - hash, - ) + const tx = await registrar.connect(registrarOwner).approve({ + name: upkeepName, + encryptedEmail: emptyBytes, + upkeepContract: mock.address, + gasLimit: performGas, + adminAddress: await admin.getAddress(), + checkData: emptyBytes, + triggerType: Trigger.CONDITION, + triggerConfig: trigger, + offchainConfig, + amount, + billingToken: linkToken.address, + }) await expect(tx).to.emit(registrar, 'RegistrationApproved') }) it('deletes the request afterwards / reverts if the request DNE', async () => { - await registrar.connect(registrarOwner).approve( - { - name: upkeepName, - encryptedEmail: emptyBytes, - upkeepContract: mock.address, - gasLimit: performGas, - adminAddress: await admin.getAddress(), - checkData: emptyBytes, - triggerType: Trigger.CONDITION, - triggerConfig: trigger, - offchainConfig, - amount, - billingToken: linkToken.address, - }, - hash, - ) - const tx = registrar.connect(registrarOwner).approve( - { - name: upkeepName, - encryptedEmail: emptyBytes, - upkeepContract: mock.address, - gasLimit: performGas, - adminAddress: await admin.getAddress(), - checkData: emptyBytes, - triggerType: Trigger.CONDITION, - triggerConfig: trigger, - offchainConfig, - amount, - billingToken: linkToken.address, - }, - hash, - ) + await registrar.connect(registrarOwner).approve({ + name: upkeepName, + encryptedEmail: emptyBytes, + upkeepContract: mock.address, + gasLimit: performGas, + adminAddress: await admin.getAddress(), + checkData: emptyBytes, + triggerType: Trigger.CONDITION, + triggerConfig: trigger, + offchainConfig, + amount, + billingToken: linkToken.address, + }) + const tx = registrar.connect(registrarOwner).approve({ + name: upkeepName, + encryptedEmail: emptyBytes, + upkeepContract: mock.address, + gasLimit: performGas, + adminAddress: await admin.getAddress(), + checkData: emptyBytes, + triggerType: Trigger.CONDITION, + triggerConfig: trigger, + offchainConfig, + amount, + billingToken: linkToken.address, + }) await evmRevertCustomError(tx, registrar, errorMsgs.requestNotFound) }) }) @@ -1049,22 +1032,19 @@ describe('AutomationRegistrar2_3', () => { await registrar.connect(registrarOwner).cancel(hash) let tx = registrar.connect(registrarOwner).cancel(hash) await evmRevertCustomError(tx, registrar, errorMsgs.requestNotFound) - tx = registrar.connect(registrarOwner).approve( - { - name: upkeepName, - encryptedEmail: emptyBytes, - upkeepContract: mock.address, - gasLimit: performGas, - adminAddress: await admin.getAddress(), - checkData: emptyBytes, - triggerType: Trigger.CONDITION, - triggerConfig: trigger, - offchainConfig: emptyBytes, - amount, - billingToken: linkToken.address, - }, - hash, - ) + tx = registrar.connect(registrarOwner).approve({ + name: upkeepName, + encryptedEmail: emptyBytes, + upkeepContract: mock.address, + gasLimit: performGas, + adminAddress: await admin.getAddress(), + checkData: emptyBytes, + triggerType: Trigger.CONDITION, + triggerConfig: trigger, + offchainConfig: emptyBytes, + amount, + billingToken: linkToken.address, + }) await evmRevertCustomError(tx, registrar, errorMsgs.requestNotFound) }) }) diff --git a/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go b/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go index dd16a290b7c..6cb4ee30be6 100644 --- a/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go +++ b/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go @@ -57,8 +57,8 @@ type AutomationRegistrar23TriggerRegistrationStorage struct { } var AutomationRegistrarMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"LINKAddress\",\"type\":\"address\"},{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"registry\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistrar2_3.InitialTriggerConfig[]\",\"name\":\"triggerConfigs\",\"type\":\"tuple[]\"},{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"minRegistrationFees\",\"type\":\"uint256[]\"},{\"internalType\":\"contractIWrappedNative\",\"name\":\"wrappedNativeToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"HashMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPayment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAdminAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBillingToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyAdminOrOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyLink\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RequestNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"AutoApproveAllowedSenderSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"displayName\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"RegistrationApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"RegistrationRejected\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"RegistrationRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"name\":\"TriggerConfigSet\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structAutomationRegistrar2_3.RegistrationParams\",\"name\":\"requestParams\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"cancel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"}],\"name\":\"getAutoApproveAllowedSender\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMinimumRegistrationAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"getPendingRequest\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRegistry\",\"outputs\":[{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"}],\"name\":\"getTriggerRegistrationDetails\",\"outputs\":[{\"components\":[{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"approvedCount\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistrar2_3.TriggerRegistrationStorage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_LINK\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_WRAPPED_NATIVE_TOKEN\",\"outputs\":[{\"internalType\":\"contractIWrappedNative\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structAutomationRegistrar2_3.RegistrationParams\",\"name\":\"requestParams\",\"type\":\"tuple\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"setAutoApproveAllowedSender\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"minBalances\",\"type\":\"uint256[]\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"name\":\"setTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60c06040523480156200001157600080fd5b506040516200358d3803806200358d8339810160408190526200003491620005db565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be8162000183565b5050506001600160a01b03808716608052811660a052620000e18584846200022e565b60005b84518110156200017657620001618582815181106200010757620001076200076d565b6020026020010151600001518683815181106200012857620001286200076d565b6020026020010151602001518784815181106200014957620001496200076d565b6020026020010151604001516200032a60201b60201c565b806200016d8162000783565b915050620000e4565b5050505050505062000804565b336001600160a01b03821603620001dd5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b62000238620003d8565b80518251146200025b57604051630dfe930960e41b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b03851617905560005b8251811015620002fb578181815181106200029857620002986200076d565b602002602001015160046000858481518110620002b957620002b96200076d565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055508080620002f29062000783565b91505062000279565b506040517fb9b6902016bd1219d5fa6161243b61e7e9f7f959526dd94ef8fa3e403bf881c390600090a1505050565b62000334620003d8565b60ff83166000908152600660205260409020805483919060ff19166001836002811115620003665762000366620007ab565b021790555060ff831660009081526006602052604090819020805464ffffffff00191661010063ffffffff851602179055517f830a6d06a4e2caac67eba04323de22bdb04f032dd8b3d6a0c52b503d9a7036a390620003cb90859085908590620007c1565b60405180910390a1505050565b6000546001600160a01b03163314620004345760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000082565b565b6001600160a01b03811681146200044c57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b03811182821017156200048a576200048a6200044f565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620004bb57620004bb6200044f565b604052919050565b60006001600160401b03821115620004df57620004df6200044f565b5060051b60200190565b600082601f830112620004fb57600080fd5b81516020620005146200050e83620004c3565b62000490565b82815260059290921b840181019181810190868411156200053457600080fd5b8286015b848110156200055c5780516200054e8162000436565b835291830191830162000538565b509695505050505050565b600082601f8301126200057957600080fd5b815160206200058c6200050e83620004c3565b82815260059290921b84018101918181019086841115620005ac57600080fd5b8286015b848110156200055c5780518352918301918301620005b0565b8051620005d68162000436565b919050565b60008060008060008060c08789031215620005f557600080fd5b8651620006028162000436565b80965050602080880151620006178162000436565b60408901519096506001600160401b03808211156200063557600080fd5b818a0191508a601f8301126200064a57600080fd5b81516200065b6200050e82620004c3565b81815260609091028301840190848101908d8311156200067a57600080fd5b938501935b8285101562000701576060858f0312156200069a5760008081fd5b620006a462000465565b855160ff81168114620006b75760008081fd5b81528587015160038110620006cc5760008081fd5b81880152604086015163ffffffff81168114620006e95760008081fd5b6040820152825260609490940193908501906200067f565b60608d015190995094505050808311156200071b57600080fd5b620007298b848c01620004e9565b955060808a01519250808311156200074057600080fd5b50506200075089828a0162000567565b9250506200076160a08801620005c9565b90509295509295509295565b634e487b7160e01b600052603260045260246000fd5b600060018201620007a457634e487b7160e01b600052601160045260246000fd5b5060010190565b634e487b7160e01b600052602160045260246000fd5b60ff841681526060810160038410620007ea57634e487b7160e01b600052602160045260246000fd5b83602083015263ffffffff83166040830152949350505050565b60805160a051612d39620008546000396000818161027b015281816105a601526106390152600081816104b301528181610a0301528181610a6c0152818161168301526116dc0152612d396000f3fe6080604052600436106101295760003560e01c806388b12d55116100a5578063accb832311610074578063befdae4611610059578063befdae46146104a1578063c4d252f5146104d5578063f2fde38b146104f557600080fd5b8063accb832314610461578063b5ff5b411461048157600080fd5b806388b12d55146103085780638da5cb5b146103d3578063a2b1ff94146103fe578063a4c0ed361461044157600080fd5b80635ab1bd53116100fc5780636bf7d75f116100e15780636bf7d75f1461026957806379ba50971461029d5780637e776f7f146102b257600080fd5b80635ab1bd53146101fd57806366ab87f91461024957600080fd5b8063181f5a771461012e578063212d08841461018d5780632ce3a14a146101ba578063367b9b4f146101db575b600080fd5b34801561013a57600080fd5b506101776040518060400160405280601981526020017f4175746f6d6174696f6e52656769737472617220322e332e300000000000000081525081565b6040516101849190611f79565b60405180910390f35b34801561019957600080fd5b506101ad6101a8366004611fa9565b610515565b604051610184919061202e565b6101cd6101c8366004612345565b6105a2565b604051908152602001610184565b3480156101e757600080fd5b506101fb6101f6366004612388565b610710565b005b34801561020957600080fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610184565b34801561025557600080fd5b506101fb610264366004612450565b6107a2565b34801561027557600080fd5b506102247f000000000000000000000000000000000000000000000000000000000000000081565b3480156102a957600080fd5b506101fb6108e9565b3480156102be57600080fd5b506102f86102cd366004612526565b73ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205460ff1690565b6040519015158152602001610184565b34801561031457600080fd5b5061039a610323366004612543565b6000908152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff169483018590526001909301549092169301929092529091565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526bffffffffffffffffffffffff909116602083015201610184565b3480156103df57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610224565b34801561040a57600080fd5b506101cd610419366004612526565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b34801561044d57600080fd5b506101fb61045c36600461255c565b6109eb565b34801561046d57600080fd5b506101fb61047c3660046125e5565b610b19565b34801561048d57600080fd5b506101fb61049c366004612630565b610c84565b3480156104ad57600080fd5b506102247f000000000000000000000000000000000000000000000000000000000000000081565b3480156104e157600080fd5b506101fb6104f0366004612543565b610d63565b34801561050157600080fd5b506101fb610510366004612526565b610f2a565b60408051606080820183526000808352602080840182905283850182905260ff86811683526006909152908490208451928301909452835492939192839116600281111561056557610565611fc4565b600281111561057657610576611fc4565b8152905463ffffffff610100820481166020840152650100000000009091041660409091015292915050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168260a0015173ffffffffffffffffffffffffffffffffffffffff1614801561060257503415155b156106bd5761061034610f3e565b82602001906bffffffffffffffffffffffff1690816bffffffffffffffffffffffff16815250507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561069f57600080fd5b505af11580156106b3573d6000803e3d6000fd5b5050505050610700565b610700333084602001516bffffffffffffffffffffffff168560a0015173ffffffffffffffffffffffffffffffffffffffff16610fe0909392919063ffffffff16565b61070a82336110c2565b92915050565b610718611529565b73ffffffffffffffffffffffffffffffffffffffff821660008181526003602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591519182527f20c6237dac83526a849285a9f79d08a483291bdd3a056a0ef9ae94ecee1ad356910160405180910390a25050565b6107aa611529565b80518251146107e5576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851617905560005b82518110156108ba5781818151811061084357610843612679565b60200260200101516004600085848151811061086157610861612679565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080806108b2906126d7565b915050610828565b506040517fb9b6902016bd1219d5fa6161243b61e7e9f7f959526dd94ef8fa3e403bf881c390600090a1505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461096f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610a5a576040517f018d10be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a6882840184612345565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168160a0015173ffffffffffffffffffffffffffffffffffffffff1614610af3576040517f018d10be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6bffffffffffffffffffffffff84166020820152610b1181866110c2565b505050505050565b610b21611529565b6000818152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff16948301949094526001909201549092169282019290925290610bcd576040517f4b13b31e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083604051602001610be091906127c3565b604051602081830303815290604052805190602001209050808314610c31576040517f3f4d605300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083815260056020526040812090815560010180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610c7d610c778561297f565b826115ac565b5050505050565b610c8c611529565b60ff8316600090815260066020526040902080548391907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836002811115610cd957610cd9611fc4565b021790555060ff83166000908152600660205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff1661010063ffffffff851602179055517f830a6d06a4e2caac67eba04323de22bdb04f032dd8b3d6a0c52b503d9a7036a390610d569085908590859061298b565b60405180910390a1505050565b6000818152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff16948301949094526001909201549092169282019290925290331480610dfd575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610e33576040517f61685c2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16610e81576040517f4b13b31e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040808320928355600190920180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905582519083015191830151610efb9273ffffffffffffffffffffffffffffffffffffffff90911691906bffffffffffffffffffffffff16611917565b60405182907f3663fb28ebc87645eb972c9dad8521bf665c623f287e79f1c56f1eb374b82a2290600090a25050565b610f32611529565b610f3b81611972565b50565b60006bffffffffffffffffffffffff821115610fdc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610966565b5090565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526110bc9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611a67565b50505050565b60a082015173ffffffffffffffffffffffffffffffffffffffff166000908152600460209081526040822054908401516bffffffffffffffffffffffff161015611138576040517fcd1c886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604083015173ffffffffffffffffffffffffffffffffffffffff16611189576040517f05bb467c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025460a08401516040517fa538b2eb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063a538b2eb90602401602060405180830381865afa1580156111fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061122191906129b6565b611257576040517f1183afea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360405160200161126a91906129d3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152600590935291205490915073ffffffffffffffffffffffffffffffffffffffff16156112fd576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836000015173ffffffffffffffffffffffffffffffffffffffff16817f7684390ebb103102f7f48c71439c2408713f8d437782a6fab2756acc0e42c1b78660c001518760e00151886060015189604001518a608001518b61012001518c61014001518d61010001518e6020015160405161137f99989796959493929190612b3f565b60405180910390a3608084015160ff908116600090815260066020526040808220815160608101909252805492936114029383911660028111156113c5576113c5611fc4565b60028111156113d6576113d6611fc4565b8152905463ffffffff610100820481166020840152650100000000009091041660409091015285611b73565b1561146a57608085015160ff166000908152600660205260409020805465010000000000900463ffffffff1690600561143a83612bfa565b91906101000a81548163ffffffff021916908363ffffffff1602179055505061146385836115ac565b9050611521565b604080516060810182528682015173ffffffffffffffffffffffffffffffffffffffff90811682526020808901516bffffffffffffffffffffffff90811682850190815260a08b01518416858701908152600089815260059094529590922093519151167401000000000000000000000000000000000000000002908216178255915160019091018054919092167fffffffffffffffffffffffff0000000000000000000000000000000000000000919091161790555b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146115aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610966565b565b60025482516060840151604080860151608087015160a08801516101008901516101208a01516101408b015195517fc62cf68400000000000000000000000000000000000000000000000000000000815260009973ffffffffffffffffffffffffffffffffffffffff16988a988a9863c62cf6849861163c98939792969095939492939092909190600401612c1d565b6020604051808303816000875af115801561165b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061167f9190612cab565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168560a0015173ffffffffffffffffffffffffffffffffffffffff16036117f65760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16634000aea08488602001518560405160200161172f91815260200190565b6040516020818303038152906040526040518463ffffffff1660e01b815260040161175c93929190612cc4565b6020604051808303816000875af115801561177b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179f91906129b6565b9050806117f0576040517f39f1c8d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610966565b506118d2565b6118378286602001516bffffffffffffffffffffffff168760a0015173ffffffffffffffffffffffffffffffffffffffff16611c189092919063ffffffff16565b60208501516040517f948108f7000000000000000000000000000000000000000000000000000000008152600481018390526bffffffffffffffffffffffff909116602482015273ffffffffffffffffffffffffffffffffffffffff83169063948108f790604401600060405180830381600087803b1580156118b957600080fd5b505af11580156118cd573d6000803e3d6000fd5b505050505b80847fb9a292fb7e3edd920cd2d2829a3615a640c43fd7de0a0820aa0668feb4c37d4b8760c001516040516119079190611f79565b60405180910390a3949350505050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905261196d9084907fa9059cbb000000000000000000000000000000000000000000000000000000009060640161103a565b505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036119f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610966565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611ac9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611d9a9092919063ffffffff16565b80519091501561196d5780806020019051810190611ae791906129b6565b61196d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610966565b60008083516002811115611b8957611b89611fc4565b03611b965750600061070a565b600183516002811115611bab57611bab611fc4565b148015611bde575073ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604090205460ff16155b15611beb5750600061070a565b826020015163ffffffff16836040015163ffffffff161015611c0f5750600161070a565b50600092915050565b801580611cb857506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611c92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cb69190612cab565b155b611d44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610966565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905261196d9084907f095ea7b3000000000000000000000000000000000000000000000000000000009060640161103a565b60606115218484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051611dce9190612d10565b60006040518083038185875af1925050503d8060008114611e0b576040519150601f19603f3d011682016040523d82523d6000602084013e611e10565b606091505b5091509150611e2187838387611e2c565b979650505050505050565b60608315611ec2578251600003611ebb5773ffffffffffffffffffffffffffffffffffffffff85163b611ebb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610966565b5081611521565b6115218383815115611ed75781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109669190611f79565b60005b83811015611f26578181015183820152602001611f0e565b50506000910152565b60008151808452611f47816020860160208601611f0b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611f8c6020830184611f2f565b9392505050565b803560ff81168114611fa457600080fd5b919050565b600060208284031215611fbb57600080fd5b611f8c82611f93565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6003811061202a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b6000606082019050612041828451611ff3565b602083015163ffffffff8082166020850152806040860151166040850152505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610160810167ffffffffffffffff811182821017156120ba576120ba612067565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561210757612107612067565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f3b57600080fd5b8035611fa48161210f565b80356bffffffffffffffffffffffff81168114611fa457600080fd5b803563ffffffff81168114611fa457600080fd5b600082601f83011261217d57600080fd5b813567ffffffffffffffff81111561219757612197612067565b6121c860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016120c0565b8181528460208386010111156121dd57600080fd5b816020850160208301376000918101602001919091529392505050565b6000610160828403121561220d57600080fd5b612215612096565b905061222082612131565b815261222e6020830161213c565b602082015261223f60408301612131565b604082015261225060608301612158565b606082015261226160808301611f93565b608082015261227260a08301612131565b60a082015260c082013567ffffffffffffffff8082111561229257600080fd5b61229e8583860161216c565b60c084015260e08401359150808211156122b757600080fd5b6122c38583860161216c565b60e0840152610100915081840135818111156122de57600080fd5b6122ea8682870161216c565b83850152506101209150818401358181111561230557600080fd5b6123118682870161216c565b83850152506101409150818401358181111561232c57600080fd5b6123388682870161216c565b8385015250505092915050565b60006020828403121561235757600080fd5b813567ffffffffffffffff81111561236e57600080fd5b611521848285016121fa565b8015158114610f3b57600080fd5b6000806040838503121561239b57600080fd5b82356123a68161210f565b915060208301356123b68161237a565b809150509250929050565b600067ffffffffffffffff8211156123db576123db612067565b5060051b60200190565b600082601f8301126123f657600080fd5b8135602061240b612406836123c1565b6120c0565b82815260059290921b8401810191818101908684111561242a57600080fd5b8286015b84811015612445578035835291830191830161242e565b509695505050505050565b60008060006060848603121561246557600080fd5b83356124708161210f565b925060208481013567ffffffffffffffff8082111561248e57600080fd5b818701915087601f8301126124a257600080fd5b81356124b0612406826123c1565b81815260059190911b8301840190848101908a8311156124cf57600080fd5b938501935b828510156124f65784356124e78161210f565b825293850193908501906124d4565b96505050604087013592508083111561250e57600080fd5b505061251c868287016123e5565b9150509250925092565b60006020828403121561253857600080fd5b8135611f8c8161210f565b60006020828403121561255557600080fd5b5035919050565b6000806000806060858703121561257257600080fd5b843561257d8161210f565b935060208501359250604085013567ffffffffffffffff808211156125a157600080fd5b818701915087601f8301126125b557600080fd5b8135818111156125c457600080fd5b8860208285010111156125d657600080fd5b95989497505060200194505050565b600080604083850312156125f857600080fd5b823567ffffffffffffffff81111561260f57600080fd5b8301610160818603121561262257600080fd5b946020939093013593505050565b60008060006060848603121561264557600080fd5b61264e84611f93565b925060208401356003811061266257600080fd5b915061267060408501612158565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612708576127086126a8565b5060010190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261274457600080fd5b830160208101925035905067ffffffffffffffff81111561276457600080fd5b80360382131561277357600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526127f1602082016127d784612131565b73ffffffffffffffffffffffffffffffffffffffff169052565b60006127ff6020840161213c565b6bffffffffffffffffffffffff811660408401525061282060408401612131565b73ffffffffffffffffffffffffffffffffffffffff811660608401525061284960608401612158565b63ffffffff811660808401525061286260808401611f93565b60ff811660a08401525061287860a08401612131565b73ffffffffffffffffffffffffffffffffffffffff811660c0840152506128a260c084018461270f565b6101608060e08601526128ba6101808601838561277a565b92506128c960e087018761270f565b92507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061010081888703018189015261290386868561277a565b9550612911818a018a61270f565b955092505061012081888703018189015261292d86868561277a565b955061293b818a018a61270f565b955092505061014081888703018189015261295786868561277a565b9550612965818a018a61270f565b955092505080878603018388015250611e2184848361277a565b600061070a36836121fa565b60ff84168152606081016129a26020830185611ff3565b63ffffffff83166040830152949350505050565b6000602082840312156129c857600080fd5b8151611f8c8161237a565b602081526129fa60208201835173ffffffffffffffffffffffffffffffffffffffff169052565b60006020830151612a1b60408401826bffffffffffffffffffffffff169052565b50604083015173ffffffffffffffffffffffffffffffffffffffff8116606084015250606083015163ffffffff8116608084015250608083015160ff811660a08401525060a083015173ffffffffffffffffffffffffffffffffffffffff811660c08401525060c08301516101608060e0850152612a9d610180850183611f2f565b915060e08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610100818786030181880152612adb8584611f2f565b945080880151925050610120818786030181880152612afa8584611f2f565b945080880151925050610140818786030181880152612b198584611f2f565b908801518782039092018488015293509050612b358382611f2f565b9695505050505050565b6000610120808352612b538184018d611f2f565b90508281036020840152612b67818c611f2f565b905063ffffffff8a16604084015273ffffffffffffffffffffffffffffffffffffffff8916606084015260ff8816608084015282810360a0840152612bac8188611f2f565b905082810360c0840152612bc08187611f2f565b905082810360e0840152612bd48186611f2f565b9150506bffffffffffffffffffffffff83166101008301529a9950505050505050505050565b600063ffffffff808316818103612c1357612c136126a8565b6001019392505050565b600061010073ffffffffffffffffffffffffffffffffffffffff808c16845263ffffffff8b166020850152808a16604085015260ff891660608501528088166080850152508060a0840152612c7481840187611f2f565b905082810360c0840152612c888186611f2f565b905082810360e0840152612c9c8185611f2f565b9b9a5050505050505050505050565b600060208284031215612cbd57600080fd5b5051919050565b73ffffffffffffffffffffffffffffffffffffffff841681526bffffffffffffffffffffffff83166020820152606060408201526000612d076060830184611f2f565b95945050505050565b60008251612d22818460208701611f0b565b919091019291505056fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"LINKAddress\",\"type\":\"address\"},{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"registry\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistrar2_3.InitialTriggerConfig[]\",\"name\":\"triggerConfigs\",\"type\":\"tuple[]\"},{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"minRegistrationFees\",\"type\":\"uint256[]\"},{\"internalType\":\"contractIWrappedNative\",\"name\":\"wrappedNativeToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"HashMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPayment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAdminAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBillingToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyAdminOrOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyLink\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RequestNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"AutoApproveAllowedSenderSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"displayName\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"RegistrationApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"RegistrationRejected\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"RegistrationRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"name\":\"TriggerConfigSet\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structAutomationRegistrar2_3.RegistrationParams\",\"name\":\"requestParams\",\"type\":\"tuple\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"cancel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"}],\"name\":\"getAutoApproveAllowedSender\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMinimumRegistrationAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"getPendingRequest\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRegistry\",\"outputs\":[{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"}],\"name\":\"getTriggerRegistrationDetails\",\"outputs\":[{\"components\":[{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"approvedCount\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistrar2_3.TriggerRegistrationStorage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_LINK\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_WRAPPED_NATIVE_TOKEN\",\"outputs\":[{\"internalType\":\"contractIWrappedNative\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structAutomationRegistrar2_3.RegistrationParams\",\"name\":\"requestParams\",\"type\":\"tuple\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"setAutoApproveAllowedSender\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"minBalances\",\"type\":\"uint256[]\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"name\":\"setTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60c06040523480156200001157600080fd5b5060405162003556380380620035568339810160408190526200003491620005db565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be8162000183565b5050506001600160a01b03808716608052811660a052620000e18584846200022e565b60005b84518110156200017657620001618582815181106200010757620001076200076d565b6020026020010151600001518683815181106200012857620001286200076d565b6020026020010151602001518784815181106200014957620001496200076d565b6020026020010151604001516200032a60201b60201c565b806200016d8162000783565b915050620000e4565b5050505050505062000804565b336001600160a01b03821603620001dd5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b62000238620003d8565b80518251146200025b57604051630dfe930960e41b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b03851617905560005b8251811015620002fb578181815181106200029857620002986200076d565b602002602001015160046000858481518110620002b957620002b96200076d565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055508080620002f29062000783565b91505062000279565b506040517fb9b6902016bd1219d5fa6161243b61e7e9f7f959526dd94ef8fa3e403bf881c390600090a1505050565b62000334620003d8565b60ff83166000908152600660205260409020805483919060ff19166001836002811115620003665762000366620007ab565b021790555060ff831660009081526006602052604090819020805464ffffffff00191661010063ffffffff851602179055517f830a6d06a4e2caac67eba04323de22bdb04f032dd8b3d6a0c52b503d9a7036a390620003cb90859085908590620007c1565b60405180910390a1505050565b6000546001600160a01b03163314620004345760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000082565b565b6001600160a01b03811681146200044c57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b03811182821017156200048a576200048a6200044f565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620004bb57620004bb6200044f565b604052919050565b60006001600160401b03821115620004df57620004df6200044f565b5060051b60200190565b600082601f830112620004fb57600080fd5b81516020620005146200050e83620004c3565b62000490565b82815260059290921b840181019181810190868411156200053457600080fd5b8286015b848110156200055c5780516200054e8162000436565b835291830191830162000538565b509695505050505050565b600082601f8301126200057957600080fd5b815160206200058c6200050e83620004c3565b82815260059290921b84018101918181019086841115620005ac57600080fd5b8286015b848110156200055c5780518352918301918301620005b0565b8051620005d68162000436565b919050565b60008060008060008060c08789031215620005f557600080fd5b8651620006028162000436565b80965050602080880151620006178162000436565b60408901519096506001600160401b03808211156200063557600080fd5b818a0191508a601f8301126200064a57600080fd5b81516200065b6200050e82620004c3565b81815260609091028301840190848101908d8311156200067a57600080fd5b938501935b8285101562000701576060858f0312156200069a5760008081fd5b620006a462000465565b855160ff81168114620006b75760008081fd5b81528587015160038110620006cc5760008081fd5b81880152604086015163ffffffff81168114620006e95760008081fd5b6040820152825260609490940193908501906200067f565b60608d015190995094505050808311156200071b57600080fd5b620007298b848c01620004e9565b955060808a01519250808311156200074057600080fd5b50506200075089828a0162000567565b9250506200076160a08801620005c9565b90509295509295509295565b634e487b7160e01b600052603260045260246000fd5b600060018201620007a457634e487b7160e01b600052601160045260246000fd5b5060010190565b634e487b7160e01b600052602160045260246000fd5b60ff841681526060810160038410620007ea57634e487b7160e01b600052602160045260246000fd5b83602083015263ffffffff83166040830152949350505050565b60805160a051612d02620008546000396000818161029b015281816105a601526106390152600081816104b301528181610b4c01528181610bb50152818161165b01526116b40152612d026000f3fe6080604052600436106101295760003560e01c80637e776f7f116100a5578063a4c0ed3611610074578063befdae4611610059578063befdae46146104a1578063c4d252f5146104d5578063f2fde38b146104f557600080fd5b8063a4c0ed3614610461578063b5ff5b411461048157600080fd5b80637e776f7f146102d257806388b12d55146103285780638da5cb5b146103f3578063a2b1ff941461041e57600080fd5b8063367b9b4f116100fc57806366ab87f9116100e157806366ab87f9146102695780636bf7d75f1461028957806379ba5097146102bd57600080fd5b8063367b9b4f146101fd5780635ab1bd531461021d57600080fd5b8063181f5a771461012e578063212d08841461018d5780632ce3a14a146101ba5780633188a2ce146101db575b600080fd5b34801561013a57600080fd5b506101776040518060400160405280601981526020017f4175746f6d6174696f6e52656769737472617220322e332e300000000000000081525081565b6040516101849190611f51565b60405180910390f35b34801561019957600080fd5b506101ad6101a8366004611f81565b610515565b6040516101849190612006565b6101cd6101c836600461231d565b6105a2565b604051908152602001610184565b3480156101e757600080fd5b506101fb6101f6366004612352565b610710565b005b34801561020957600080fd5b506101fb61021836600461239c565b610859565b34801561022957600080fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610184565b34801561027557600080fd5b506101fb610284366004612464565b6108eb565b34801561029557600080fd5b506102447f000000000000000000000000000000000000000000000000000000000000000081565b3480156102c957600080fd5b506101fb610a32565b3480156102de57600080fd5b506103186102ed36600461253a565b73ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205460ff1690565b6040519015158152602001610184565b34801561033457600080fd5b506103ba610343366004612557565b6000908152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff169483018590526001909301549092169301929092529091565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526bffffffffffffffffffffffff909116602083015201610184565b3480156103ff57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610244565b34801561042a57600080fd5b506101cd61043936600461253a565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b34801561046d57600080fd5b506101fb61047c366004612570565b610b34565b34801561048d57600080fd5b506101fb61049c3660046125f9565b610c62565b3480156104ad57600080fd5b506102447f000000000000000000000000000000000000000000000000000000000000000081565b3480156104e157600080fd5b506101fb6104f0366004612557565b610d41565b34801561050157600080fd5b506101fb61051036600461253a565b610f08565b60408051606080820183526000808352602080840182905283850182905260ff86811683526006909152908490208451928301909452835492939192839116600281111561056557610565611f9c565b600281111561057657610576611f9c565b8152905463ffffffff610100820481166020840152650100000000009091041660409091015292915050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168260a0015173ffffffffffffffffffffffffffffffffffffffff1614801561060257503415155b156106bd5761061034610f1c565b82602001906bffffffffffffffffffffffff1690816bffffffffffffffffffffffff16815250507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561069f57600080fd5b505af11580156106b3573d6000803e3d6000fd5b5050505050610700565b610700333084602001516bffffffffffffffffffffffff168560a0015173ffffffffffffffffffffffffffffffffffffffff16610fbe909392919063ffffffff16565b61070a823361109a565b92915050565b610718611501565b60008160405160200161072b91906126f6565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00181528282528051602091820120600081815260058352839020606085018452805473ffffffffffffffffffffffffffffffffffffffff808216808852740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff169487019490945260019091015490921692840192909252909250610807576040517f4b13b31e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260056020526040812090815560010180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561085361084d846128b2565b83611584565b50505050565b610861611501565b73ffffffffffffffffffffffffffffffffffffffff821660008181526003602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591519182527f20c6237dac83526a849285a9f79d08a483291bdd3a056a0ef9ae94ecee1ad356910160405180910390a25050565b6108f3611501565b805182511461092e576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851617905560005b8251811015610a035781818151811061098c5761098c6128be565b6020026020010151600460008584815181106109aa576109aa6128be565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080806109fb9061291c565b915050610971565b506040517fb9b6902016bd1219d5fa6161243b61e7e9f7f959526dd94ef8fa3e403bf881c390600090a1505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610ab8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610ba3576040517f018d10be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610bb18284018461231d565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168160a0015173ffffffffffffffffffffffffffffffffffffffff1614610c3c576040517f018d10be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6bffffffffffffffffffffffff84166020820152610c5a818661109a565b505050505050565b610c6a611501565b60ff8316600090815260066020526040902080548391907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836002811115610cb757610cb7611f9c565b021790555060ff83166000908152600660205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff1661010063ffffffff851602179055517f830a6d06a4e2caac67eba04323de22bdb04f032dd8b3d6a0c52b503d9a7036a390610d3490859085908590612954565b60405180910390a1505050565b6000818152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff16948301949094526001909201549092169282019290925290331480610ddb575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610e11576040517f61685c2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16610e5f576040517f4b13b31e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040808320928355600190920180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905582519083015191830151610ed99273ffffffffffffffffffffffffffffffffffffffff90911691906bffffffffffffffffffffffff166118ef565b60405182907f3663fb28ebc87645eb972c9dad8521bf665c623f287e79f1c56f1eb374b82a2290600090a25050565b610f10611501565b610f198161194a565b50565b60006bffffffffffffffffffffffff821115610fba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610aaf565b5090565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526108539085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611a3f565b60a082015173ffffffffffffffffffffffffffffffffffffffff166000908152600460209081526040822054908401516bffffffffffffffffffffffff161015611110576040517fcd1c886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604083015173ffffffffffffffffffffffffffffffffffffffff16611161576040517f05bb467c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025460a08401516040517fa538b2eb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063a538b2eb90602401602060405180830381865afa1580156111d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f9919061297f565b61122f576040517f1183afea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083604051602001611242919061299c565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152600590935291205490915073ffffffffffffffffffffffffffffffffffffffff16156112d5576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836000015173ffffffffffffffffffffffffffffffffffffffff16817f7684390ebb103102f7f48c71439c2408713f8d437782a6fab2756acc0e42c1b78660c001518760e00151886060015189604001518a608001518b61012001518c61014001518d61010001518e6020015160405161135799989796959493929190612b08565b60405180910390a3608084015160ff908116600090815260066020526040808220815160608101909252805492936113da93839116600281111561139d5761139d611f9c565b60028111156113ae576113ae611f9c565b8152905463ffffffff610100820481166020840152650100000000009091041660409091015285611b4b565b1561144257608085015160ff166000908152600660205260409020805465010000000000900463ffffffff1690600561141283612bc3565b91906101000a81548163ffffffff021916908363ffffffff1602179055505061143b8583611584565b90506114f9565b604080516060810182528682015173ffffffffffffffffffffffffffffffffffffffff90811682526020808901516bffffffffffffffffffffffff90811682850190815260a08b01518416858701908152600089815260059094529590922093519151167401000000000000000000000000000000000000000002908216178255915160019091018054919092167fffffffffffffffffffffffff0000000000000000000000000000000000000000919091161790555b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611582576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610aaf565b565b60025482516060840151604080860151608087015160a08801516101008901516101208a01516101408b015195517fc62cf68400000000000000000000000000000000000000000000000000000000815260009973ffffffffffffffffffffffffffffffffffffffff16988a988a9863c62cf6849861161498939792969095939492939092909190600401612be6565b6020604051808303816000875af1158015611633573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116579190612c74565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168560a0015173ffffffffffffffffffffffffffffffffffffffff16036117ce5760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16634000aea08488602001518560405160200161170791815260200190565b6040516020818303038152906040526040518463ffffffff1660e01b815260040161173493929190612c8d565b6020604051808303816000875af1158015611753573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611777919061297f565b9050806117c8576040517f39f1c8d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610aaf565b506118aa565b61180f8286602001516bffffffffffffffffffffffff168760a0015173ffffffffffffffffffffffffffffffffffffffff16611bf09092919063ffffffff16565b60208501516040517f948108f7000000000000000000000000000000000000000000000000000000008152600481018390526bffffffffffffffffffffffff909116602482015273ffffffffffffffffffffffffffffffffffffffff83169063948108f790604401600060405180830381600087803b15801561189157600080fd5b505af11580156118a5573d6000803e3d6000fd5b505050505b80847fb9a292fb7e3edd920cd2d2829a3615a640c43fd7de0a0820aa0668feb4c37d4b8760c001516040516118df9190611f51565b60405180910390a3949350505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526119459084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401611018565b505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036119c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610aaf565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611aa1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611d729092919063ffffffff16565b8051909150156119455780806020019051810190611abf919061297f565b611945576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610aaf565b60008083516002811115611b6157611b61611f9c565b03611b6e5750600061070a565b600183516002811115611b8357611b83611f9c565b148015611bb6575073ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604090205460ff16155b15611bc35750600061070a565b826020015163ffffffff16836040015163ffffffff161015611be75750600161070a565b50600092915050565b801580611c9057506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611c6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8e9190612c74565b155b611d1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610aaf565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526119459084907f095ea7b30000000000000000000000000000000000000000000000000000000090606401611018565b60606114f98484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051611da69190612cd9565b60006040518083038185875af1925050503d8060008114611de3576040519150601f19603f3d011682016040523d82523d6000602084013e611de8565b606091505b5091509150611df987838387611e04565b979650505050505050565b60608315611e9a578251600003611e935773ffffffffffffffffffffffffffffffffffffffff85163b611e93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610aaf565b50816114f9565b6114f98383815115611eaf5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aaf9190611f51565b60005b83811015611efe578181015183820152602001611ee6565b50506000910152565b60008151808452611f1f816020860160208601611ee3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611f646020830184611f07565b9392505050565b803560ff81168114611f7c57600080fd5b919050565b600060208284031215611f9357600080fd5b611f6482611f6b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60038110612002577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b6000606082019050612019828451611fcb565b602083015163ffffffff8082166020850152806040860151166040850152505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610160810167ffffffffffffffff811182821017156120925761209261203f565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156120df576120df61203f565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f1957600080fd5b8035611f7c816120e7565b80356bffffffffffffffffffffffff81168114611f7c57600080fd5b803563ffffffff81168114611f7c57600080fd5b600082601f83011261215557600080fd5b813567ffffffffffffffff81111561216f5761216f61203f565b6121a060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612098565b8181528460208386010111156121b557600080fd5b816020850160208301376000918101602001919091529392505050565b600061016082840312156121e557600080fd5b6121ed61206e565b90506121f882612109565b815261220660208301612114565b602082015261221760408301612109565b604082015261222860608301612130565b606082015261223960808301611f6b565b608082015261224a60a08301612109565b60a082015260c082013567ffffffffffffffff8082111561226a57600080fd5b61227685838601612144565b60c084015260e084013591508082111561228f57600080fd5b61229b85838601612144565b60e0840152610100915081840135818111156122b657600080fd5b6122c286828701612144565b8385015250610120915081840135818111156122dd57600080fd5b6122e986828701612144565b83850152506101409150818401358181111561230457600080fd5b61231086828701612144565b8385015250505092915050565b60006020828403121561232f57600080fd5b813567ffffffffffffffff81111561234657600080fd5b6114f9848285016121d2565b60006020828403121561236457600080fd5b813567ffffffffffffffff81111561237b57600080fd5b82016101608185031215611f6457600080fd5b8015158114610f1957600080fd5b600080604083850312156123af57600080fd5b82356123ba816120e7565b915060208301356123ca8161238e565b809150509250929050565b600067ffffffffffffffff8211156123ef576123ef61203f565b5060051b60200190565b600082601f83011261240a57600080fd5b8135602061241f61241a836123d5565b612098565b82815260059290921b8401810191818101908684111561243e57600080fd5b8286015b848110156124595780358352918301918301612442565b509695505050505050565b60008060006060848603121561247957600080fd5b8335612484816120e7565b925060208481013567ffffffffffffffff808211156124a257600080fd5b818701915087601f8301126124b657600080fd5b81356124c461241a826123d5565b81815260059190911b8301840190848101908a8311156124e357600080fd5b938501935b8285101561250a5784356124fb816120e7565b825293850193908501906124e8565b96505050604087013592508083111561252257600080fd5b5050612530868287016123f9565b9150509250925092565b60006020828403121561254c57600080fd5b8135611f64816120e7565b60006020828403121561256957600080fd5b5035919050565b6000806000806060858703121561258657600080fd5b8435612591816120e7565b935060208501359250604085013567ffffffffffffffff808211156125b557600080fd5b818701915087601f8301126125c957600080fd5b8135818111156125d857600080fd5b8860208285010111156125ea57600080fd5b95989497505060200194505050565b60008060006060848603121561260e57600080fd5b61261784611f6b565b925060208401356003811061262b57600080fd5b915061263960408501612130565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261267757600080fd5b830160208101925035905067ffffffffffffffff81111561269757600080fd5b8036038213156126a657600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526127246020820161270a84612109565b73ffffffffffffffffffffffffffffffffffffffff169052565b600061273260208401612114565b6bffffffffffffffffffffffff811660408401525061275360408401612109565b73ffffffffffffffffffffffffffffffffffffffff811660608401525061277c60608401612130565b63ffffffff811660808401525061279560808401611f6b565b60ff811660a0840152506127ab60a08401612109565b73ffffffffffffffffffffffffffffffffffffffff811660c0840152506127d560c0840184612642565b6101608060e08601526127ed610180860183856126ad565b92506127fc60e0870187612642565b92507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06101008188870301818901526128368686856126ad565b9550612844818a018a612642565b95509250506101208188870301818901526128608686856126ad565b955061286e818a018a612642565b955092505061014081888703018189015261288a8686856126ad565b9550612898818a018a612642565b955092505080878603018388015250611df98484836126ad565b600061070a36836121d2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361294d5761294d6128ed565b5060010190565b60ff841681526060810161296b6020830185611fcb565b63ffffffff83166040830152949350505050565b60006020828403121561299157600080fd5b8151611f648161238e565b602081526129c360208201835173ffffffffffffffffffffffffffffffffffffffff169052565b600060208301516129e460408401826bffffffffffffffffffffffff169052565b50604083015173ffffffffffffffffffffffffffffffffffffffff8116606084015250606083015163ffffffff8116608084015250608083015160ff811660a08401525060a083015173ffffffffffffffffffffffffffffffffffffffff811660c08401525060c08301516101608060e0850152612a66610180850183611f07565b915060e08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610100818786030181880152612aa48584611f07565b945080880151925050610120818786030181880152612ac38584611f07565b945080880151925050610140818786030181880152612ae28584611f07565b908801518782039092018488015293509050612afe8382611f07565b9695505050505050565b6000610120808352612b1c8184018d611f07565b90508281036020840152612b30818c611f07565b905063ffffffff8a16604084015273ffffffffffffffffffffffffffffffffffffffff8916606084015260ff8816608084015282810360a0840152612b758188611f07565b905082810360c0840152612b898187611f07565b905082810360e0840152612b9d8186611f07565b9150506bffffffffffffffffffffffff83166101008301529a9950505050505050505050565b600063ffffffff808316818103612bdc57612bdc6128ed565b6001019392505050565b600061010073ffffffffffffffffffffffffffffffffffffffff808c16845263ffffffff8b166020850152808a16604085015260ff891660608501528088166080850152508060a0840152612c3d81840187611f07565b905082810360c0840152612c518186611f07565b905082810360e0840152612c658185611f07565b9b9a5050505050505050505050565b600060208284031215612c8657600080fd5b5051919050565b73ffffffffffffffffffffffffffffffffffffffff841681526bffffffffffffffffffffffff83166020820152606060408201526000612cd06060830184611f07565b95945050505050565b60008251612ceb818460208701611ee3565b919091019291505056fea164736f6c6343000813000a", } var AutomationRegistrarABI = AutomationRegistrarMetaData.ABI @@ -408,16 +408,16 @@ func (_AutomationRegistrar *AutomationRegistrarTransactorSession) AcceptOwnershi return _AutomationRegistrar.Contract.AcceptOwnership(&_AutomationRegistrar.TransactOpts) } -func (_AutomationRegistrar *AutomationRegistrarTransactor) Approve(opts *bind.TransactOpts, requestParams AutomationRegistrar23RegistrationParams, hash [32]byte) (*types.Transaction, error) { - return _AutomationRegistrar.contract.Transact(opts, "approve", requestParams, hash) +func (_AutomationRegistrar *AutomationRegistrarTransactor) Approve(opts *bind.TransactOpts, requestParams AutomationRegistrar23RegistrationParams) (*types.Transaction, error) { + return _AutomationRegistrar.contract.Transact(opts, "approve", requestParams) } -func (_AutomationRegistrar *AutomationRegistrarSession) Approve(requestParams AutomationRegistrar23RegistrationParams, hash [32]byte) (*types.Transaction, error) { - return _AutomationRegistrar.Contract.Approve(&_AutomationRegistrar.TransactOpts, requestParams, hash) +func (_AutomationRegistrar *AutomationRegistrarSession) Approve(requestParams AutomationRegistrar23RegistrationParams) (*types.Transaction, error) { + return _AutomationRegistrar.Contract.Approve(&_AutomationRegistrar.TransactOpts, requestParams) } -func (_AutomationRegistrar *AutomationRegistrarTransactorSession) Approve(requestParams AutomationRegistrar23RegistrationParams, hash [32]byte) (*types.Transaction, error) { - return _AutomationRegistrar.Contract.Approve(&_AutomationRegistrar.TransactOpts, requestParams, hash) +func (_AutomationRegistrar *AutomationRegistrarTransactorSession) Approve(requestParams AutomationRegistrar23RegistrationParams) (*types.Transaction, error) { + return _AutomationRegistrar.Contract.Approve(&_AutomationRegistrar.TransactOpts, requestParams) } func (_AutomationRegistrar *AutomationRegistrarTransactor) Cancel(opts *bind.TransactOpts, hash [32]byte) (*types.Transaction, error) { @@ -1633,7 +1633,7 @@ type AutomationRegistrarInterface interface { AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - Approve(opts *bind.TransactOpts, requestParams AutomationRegistrar23RegistrationParams, hash [32]byte) (*types.Transaction, error) + Approve(opts *bind.TransactOpts, requestParams AutomationRegistrar23RegistrationParams) (*types.Transaction, error) Cancel(opts *bind.TransactOpts, hash [32]byte) (*types.Transaction, error) diff --git a/core/gethwrappers/generated/automation_registry_logic_a_wrapper_2_3/automation_registry_logic_a_wrapper_2_3.go b/core/gethwrappers/generated/automation_registry_logic_a_wrapper_2_3/automation_registry_logic_a_wrapper_2_3.go index 891415c7d3a..d08825fa1f4 100644 --- a/core/gethwrappers/generated/automation_registry_logic_a_wrapper_2_3/automation_registry_logic_a_wrapper_2_3.go +++ b/core/gethwrappers/generated/automation_registry_logic_a_wrapper_2_3/automation_registry_logic_a_wrapper_2_3.go @@ -46,7 +46,7 @@ type AutomationRegistryBase23BillingOverrides struct { var AutomationRegistryLogicAMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"contractAutomationRegistryLogicB2_3\",\"name\":\"logicB\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contractIERC20Metadata\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"cancelUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"migrateUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedUpkeeps\",\"type\":\"bytes\"}],\"name\":\"receiveUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"enumAutomationRegistryBase2_3.Trigger\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101806040523480156200001257600080fd5b506040516200477c3803806200477c83398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e0516101005161012051610140516101605161406862000714600039600081816088015260de01526000505060005050600081816111bd01526114d60152600050506000505060005050600050506140686000f3fe608060405260043610620000865760003560e01c80638e86139b11620000555780638e86139b1462000192578063c62cf68414620001b7578063c804802214620001eb578063f2fde38b14620002105762000086565b8063349e8cca14620000ce57806379ba5097146200012857806385c1b0ba14620001405780638da5cb5b1462000165575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e808015620000c7573d6000f35b3d6000fd5b005b348015620000db57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156200013557600080fd5b50620000cc62000235565b3480156200014d57600080fd5b50620000cc6200015f36600462002cac565b62000338565b3480156200017257600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16620000fe565b3480156200019f57600080fd5b50620000cc620001b136600462002d85565b62001080565b348015620001c457600080fd5b50620001dc620001d636600462002f43565b62001408565b6040519081526020016200011f565b348015620001f857600080fd5b50620000cc6200020a36600462003038565b620017b5565b3480156200021d57600080fd5b50620000cc6200022f36600462003052565b62001c8d565b60015473ffffffffffffffffffffffffffffffffffffffff163314620002bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b600173ffffffffffffffffffffffffffffffffffffffff82166000908152601c602052604090205460ff16600381111562000377576200037762003079565b14158015620003c35750600373ffffffffffffffffffffffffffffffffffffffff82166000908152601c602052604090205460ff166003811115620003c057620003c062003079565b14155b15620003fb576040517f0ebeec3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60165473ffffffffffffffffffffffffffffffffffffffff166200044b576040517fd12d7d8d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082900362000487576040517f2c2fc94100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290528190819060008667ffffffffffffffff811115620004f157620004f162002df0565b6040519080825280602002602001820160405280156200051b578160200160208202803683370190505b50905060008767ffffffffffffffff8111156200053c576200053c62002df0565b604051908082528060200260200182016040528015620005d357816020015b604080516101208101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e0820181905261010082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816200055b5790505b50905060008867ffffffffffffffff811115620005f457620005f462002df0565b6040519080825280602002602001820160405280156200062957816020015b6060815260200190600190039081620006135790505b50905060008967ffffffffffffffff8111156200064a576200064a62002df0565b6040519080825280602002602001820160405280156200067f57816020015b6060815260200190600190039081620006695790505b50905060008a67ffffffffffffffff811115620006a057620006a062002df0565b604051908082528060200260200182016040528015620006d557816020015b6060815260200190600190039081620006bf5790505b50905060005b8b81101562000def578c8c82818110620006f957620006f9620030a8565b602090810292909201356000818152600484526040808220815161012081018352815460ff8082161515835261010080830490911615159883019890985263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e082015260029091015490911694810194909452909a5091985050819003620008305786610100015199508660c001516bffffffffffffffffffffffff1698505b8973ffffffffffffffffffffffffffffffffffffffff1687610100015173ffffffffffffffffffffffffffffffffffffffff1614620008f55773ffffffffffffffffffffffffffffffffffffffff8a166000908152602160205260409020546200089c908a9062003106565b73ffffffffffffffffffffffffffffffffffffffff8b16600081815260216020526040902091909155620008d2908c8b62001ca5565b86610100015199508660c001516bffffffffffffffffffffffff1698506200091e565b80156200091e5760c08701516200091b906bffffffffffffffffffffffff168a6200311c565b98505b620009298862001d39565b60808701516040517f1a5da6c800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8d8116600483015290911690631a5da6c890602401600060405180830381600087803b1580156200099957600080fd5b505af1158015620009ae573d6000803e3d6000fd5b5050505086858281518110620009c857620009c8620030a8565b60200260200101819052506005600089815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1686828151811062000a1c5762000a1c620030a8565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091018201526000898152600790915260409020805462000a5b9062003132565b80601f016020809104026020016040519081016040528092919081815260200182805462000a899062003132565b801562000ada5780601f1062000aae5761010080835404028352916020019162000ada565b820191906000526020600020905b81548152906001019060200180831162000abc57829003601f168201915b505050505084828151811062000af45762000af4620030a8565b6020026020010181905250601d6000898152602001908152602001600020805462000b1f9062003132565b80601f016020809104026020016040519081016040528092919081815260200182805462000b4d9062003132565b801562000b9e5780601f1062000b725761010080835404028352916020019162000b9e565b820191906000526020600020905b81548152906001019060200180831162000b8057829003601f168201915b505050505083828151811062000bb85762000bb8620030a8565b6020026020010181905250601e6000898152602001908152602001600020805462000be39062003132565b80601f016020809104026020016040519081016040528092919081815260200182805462000c119062003132565b801562000c625780601f1062000c365761010080835404028352916020019162000c62565b820191906000526020600020905b81548152906001019060200180831162000c4457829003601f168201915b505050505082828151811062000c7c5762000c7c620030a8565b602090810291909101810191909152600089815260048252604080822080547fffff0000000000000000000000000000000000000000000000000000000000001681556001810183905560020180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055600790925290812062000d029162002c0f565b6000888152601d6020526040812062000d1b9162002c0f565b6000888152601e6020526040812062000d349162002c0f565b600088815260066020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016905562000d7560028962001df0565b5060c0870151604080516bffffffffffffffffffffffff909216825273ffffffffffffffffffffffffffffffffffffffff8d16602083015289917fb38647142fbb1ea4c000fc4569b37a4e9a9f6313317b84ee3e5326c1a6cd06ff910160405180910390a28062000de68162003187565b915050620006db565b5073ffffffffffffffffffffffffffffffffffffffff891660009081526021602052604090205462000e2390899062003106565b73ffffffffffffffffffffffffffffffffffffffff8a1660008181526021602052604090209190915562000e59908b8a62001ca5565b60008c8c868167ffffffffffffffff81111562000e7a5762000e7a62002df0565b60405190808252806020026020018201604052801562000ea4578160200160208202803683370190505b508988888860405160200162000ec2989796959493929190620033b9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282526016547faab9edd6000000000000000000000000000000000000000000000000000000008452915190935073ffffffffffffffffffffffffffffffffffffffff808f1693638e86139b939091169163c71249ab91600491869163aab9edd6918482019160209190819003860181865afa15801562000f72573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000f98919062003498565b866040518463ffffffff1660e01b815260040162000fb993929190620034bd565b600060405180830381865afa15801562000fd7573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526200101f9190810190620034e4565b6040518263ffffffff1660e01b81526004016200103d91906200355b565b600060405180830381600087803b1580156200105857600080fd5b505af11580156200106d573d6000803e3d6000fd5b5050505050505050505050505050505050565b6002336000908152601c602052604090205460ff166003811115620010a957620010a962003079565b14158015620010df57506003336000908152601c602052604090205460ff166003811115620010dc57620010dc62003079565b14155b1562001117576040517f0ebeec3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008080808080806200112d888a018a62003882565b965096509650965096509650965060005b8751811015620013fc57600073ffffffffffffffffffffffffffffffffffffffff16878281518110620011755762001175620030a8565b60200260200101516080015173ffffffffffffffffffffffffffffffffffffffff16036200128957858181518110620011b257620011b2620030a8565b6020026020010151307f0000000000000000000000000000000000000000000000000000000000000000604051620011ea9062002c4e565b73ffffffffffffffffffffffffffffffffffffffff938416815291831660208301529091166040820152606001604051809103906000f08015801562001234573d6000803e3d6000fd5b508782815181106200124a576200124a620030a8565b60200260200101516080019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b62001341888281518110620012a257620012a2620030a8565b6020026020010151888381518110620012bf57620012bf620030a8565b6020026020010151878481518110620012dc57620012dc620030a8565b6020026020010151878581518110620012f957620012f9620030a8565b6020026020010151878681518110620013165762001316620030a8565b6020026020010151878781518110620013335762001333620030a8565b602002602001015162001e07565b878181518110620013565762001356620030a8565b60200260200101517f74931a144e43a50694897f241d973aecb5024c0e910f9bb80a163ea3c1cf5a71888381518110620013945762001394620030a8565b602002602001015160c0015133604051620013df9291906bffffffffffffffffffffffff92909216825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b60405180910390a280620013f38162003187565b9150506200113e565b50505050505050505050565b6000805473ffffffffffffffffffffffffffffffffffffffff1633148015906200143c57506200143a60093362002324565b155b1562001474576040517fd48b678b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a163b620014c3576040517f09ee12d500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620014ce8762002354565b905060008a307f0000000000000000000000000000000000000000000000000000000000000000604051620015039062002c4e565b73ffffffffffffffffffffffffffffffffffffffff938416815291831660208301529091166040820152606001604051809103906000f0801580156200154d573d6000803e3d6000fd5b5090506200163e826040518061012001604052806000151581526020016000151581526020018d63ffffffff16815260200163ffffffff801681526020018473ffffffffffffffffffffffffffffffffffffffff16815260200160006fffffffffffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff168152602001600063ffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff168152508b89898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b92508a915062001e079050565b601680547c0100000000000000000000000000000000000000000000000000000000900463ffffffff1690601c6200167683620039b3565b91906101000a81548163ffffffff021916908363ffffffff16021790555050817fbae366358c023f887e791d7a62f2e4316f1026bd77f6fb49501a917b3bc5d0128b8b604051620016ef92919063ffffffff92909216825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b60405180910390a2817fcba2d5723b2ee59e53a8e8a82a4a7caf4fdfe70e9f7c582950bf7e7a5c24e83d87876040516200172b929190620039d9565b60405180910390a2817f2b72ac786c97e68dbab71023ed6f2bdbfc80ad9bb7808941929229d71b7d5664856040516200176591906200355b565b60405180910390a2817f3e8740446213c8a77d40e08f79136ce3f347d13ed270a6ebdf57159e0faf4850846040516200179f91906200355b565b60405180910390a2509998505050505050505050565b6000818152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e08201526002909101549091169181019190915290620018d960005473ffffffffffffffffffffffffffffffffffffffff1690565b61010083015173ffffffffffffffffffffffffffffffffffffffff90811660009081526022602090815260408083206002015460155482517f57e871e70000000000000000000000000000000000000000000000000000000081529251968616331497506bffffffffffffffffffffffff90911695939416926357e871e7926004808401939192918290030181865afa1580156200197b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620019a1919062003a26565b9050836060015163ffffffff16600003620019e8576040517ffbc0357800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606084015163ffffffff9081161462001a2d576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8215801562001a60575060008581526005602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b1562001a98576040517ffbdb8e5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8262001aae5762001aab6032826200311c565b90505b6000858152600460205260409020805463ffffffff8084166601000000000000027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff9092169190911790915562001b0b90600290879062001df016565b506000826bffffffffffffffffffffffff168560a001516fffffffffffffffffffffffffffffffff16101562001b7e5760a085015162001b4c908462003a40565b90508460c001516bffffffffffffffffffffffff16816bffffffffffffffffffffffff16111562001b7e575060c08401515b808560c0015162001b90919062003a40565b600087815260046020908152604080832060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000006bffffffffffffffffffffffff9687160217905561010089015173ffffffffffffffffffffffffffffffffffffffff168352602190915290205462001c229183169062003106565b61010086015173ffffffffffffffffffffffffffffffffffffffff1660009081526021602052604080822092909255905167ffffffffffffffff84169188917f91cb3bb75cfbd718bbfccc56b7f53d92d7048ef4ca39a3b7b7c6d4af1f7911819190a3505050505050565b62001c97620025f3565b62001ca28162002678565b50565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905262001d349084906200276f565b505050565b60008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff16331462001d97576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020546601000000000000900463ffffffff9081161462001ca2576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600062001dfe838362002882565b90505b92915050565b601454760100000000000000000000000000000000000000000000900460ff161562001e5f576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60175483517c010000000000000000000000000000000000000000000000000000000090910463ffffffff16101562001ec4576040517fae7235df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108fc856040015163ffffffff16108062001f0a5750601654604086015163ffffffff780100000000000000000000000000000000000000000000000090920482169116115b1562001f42576040517f14c237fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000868152600460205260409020546a0100000000000000000000900473ffffffffffffffffffffffffffffffffffffffff161562001fad576040517f6e3b930b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010085015173ffffffffffffffffffffffffffffffffffffffff9081166000908152602260205260409020546701000000000000009004166200201d576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846004600088815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555060408201518160000160026101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160066101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600a6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160010160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160010160106101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050836005600088815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260076000888152602001908152602001600020908162002262919062003aba565b5060c085015161010086015173ffffffffffffffffffffffffffffffffffffffff16600090815260216020526040902054620022ad916bffffffffffffffffffffffff16906200311c565b61010086015173ffffffffffffffffffffffffffffffffffffffff16600090815260216020908152604080832093909355888252601d905220620022f2838262003aba565b506000868152601e602052604090206200230d828262003aba565b506200231b6002876200298d565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151562001dfe565b601554604080517f57e871e70000000000000000000000000000000000000000000000000000000081529051600092839273ffffffffffffffffffffffffffffffffffffffff90911691839183916385df51fd9160019184916357e871e79160048083019260209291908290030181865afa158015620023d8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620023fe919062003a26565b6200240a919062003106565b6040518263ffffffff1660e01b81526004016200242991815260200190565b602060405180830381865afa15801562002447573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200246d919062003a26565b60165460408051602081019390935230908301527c0100000000000000000000000000000000000000000000000000000000900463ffffffff166060820152608001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083015201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060045b600f8110156200258157838282815181106200253d576200253d620030a8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080620025788162003187565b9150506200251d565b5084600181111562002597576200259762003079565b60f81b81600f81518110620025b057620025b0620030a8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350620025ea8162003be1565b95945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331462002676576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401620002b3565b565b3373ffffffffffffffffffffffffffffffffffffffff821603620026f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620002b3565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000620027d3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166200299b9092919063ffffffff16565b80519091501562001d345780806020019051810190620027f4919062003c24565b62001d34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401620002b3565b600081815260018301602052604081205480156200297b576000620028a960018362003106565b8554909150600090620028bf9060019062003106565b90508181146200292b576000866000018281548110620028e357620028e3620030a8565b9060005260206000200154905080876000018481548110620029095762002909620030a8565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200293f576200293f62003c44565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062001e01565b600091505062001e01565b5092915050565b600062001dfe8383620029b4565b6060620029ac848460008562002a06565b949350505050565b6000818152600183016020526040812054620029fd5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562001e01565b50600062001e01565b60608247101562002a9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401620002b3565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405162002ac5919062003c73565b60006040518083038185875af1925050503d806000811462002b04576040519150601f19603f3d011682016040523d82523d6000602084013e62002b09565b606091505b509150915062002b1c8783838762002b27565b979650505050505050565b6060831562002bc257825160000362002bba5773ffffffffffffffffffffffffffffffffffffffff85163b62002bba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620002b3565b5081620029ac565b620029ac838381511562002bd95781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002b391906200355b565b50805462002c1d9062003132565b6000825580601f1062002c2e575050565b601f01602090049060005260206000209081019062001ca2919062002c5c565b6103ca8062003c9283390190565b5b8082111562002c73576000815560010162002c5d565b5090565b73ffffffffffffffffffffffffffffffffffffffff8116811462001ca257600080fd5b803562002ca78162002c77565b919050565b60008060006040848603121562002cc257600080fd5b833567ffffffffffffffff8082111562002cdb57600080fd5b818601915086601f83011262002cf057600080fd5b81358181111562002d0057600080fd5b8760208260051b850101111562002d1657600080fd5b6020928301955093505084013562002d2e8162002c77565b809150509250925092565b60008083601f84011262002d4c57600080fd5b50813567ffffffffffffffff81111562002d6557600080fd5b60208301915083602082850101111562002d7e57600080fd5b9250929050565b6000806020838503121562002d9957600080fd5b823567ffffffffffffffff81111562002db157600080fd5b62002dbf8582860162002d39565b90969095509350505050565b803563ffffffff8116811462002ca757600080fd5b80356002811062002ca757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171562002e465762002e4662002df0565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171562002e965762002e9662002df0565b604052919050565b600067ffffffffffffffff82111562002ebb5762002ebb62002df0565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011262002ef957600080fd5b813562002f1062002f0a8262002e9e565b62002e4c565b81815284602083860101111562002f2657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060008060006101008a8c03121562002f6357600080fd5b62002f6e8a62002c9a565b985062002f7e60208b0162002dcb565b975062002f8e60408b0162002c9a565b965062002f9e60608b0162002de0565b955062002fae60808b0162002c9a565b945060a08a013567ffffffffffffffff8082111562002fcc57600080fd5b62002fda8d838e0162002d39565b909650945060c08c013591508082111562002ff457600080fd5b620030028d838e0162002ee7565b935060e08c01359150808211156200301957600080fd5b50620030288c828d0162002ee7565b9150509295985092959850929598565b6000602082840312156200304b57600080fd5b5035919050565b6000602082840312156200306557600080fd5b8135620030728162002c77565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111562001e015762001e01620030d7565b8082018082111562001e015762001e01620030d7565b600181811c908216806200314757607f821691505b60208210810362003181577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620031bb57620031bb620030d7565b5060010190565b600081518084526020808501945080840160005b838110156200329b5781518051151588528381015115158489015260408082015163ffffffff908116918a01919091526060808301518216908a015260808083015173ffffffffffffffffffffffffffffffffffffffff908116918b019190915260a0808401516fffffffffffffffffffffffffffffffff16908b015260c0808401516bffffffffffffffffffffffff16908b015260e080840151909216918a01919091526101009182015116908801526101209096019590820190600101620031d6565b509495945050505050565b600081518084526020808501945080840160005b838110156200329b57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101620032ba565b60005b838110156200330b578181015183820152602001620032f1565b50506000910152565b600081518084526200332e816020860160208601620032ee565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b85811015620033ac5782840389526200339984835162003314565b988501989350908401906001016200337e565b5091979650505050505050565b60e081528760e082015260006101007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8a1115620033f657600080fd5b8960051b808c838601378301838103820160208501526200341a8282018b620031c2565b9150508281036040840152620034318189620032a6565b90508281036060840152620034478188620032a6565b905082810360808401526200345d818762003360565b905082810360a084015262003473818662003360565b905082810360c084015262003489818562003360565b9b9a5050505050505050505050565b600060208284031215620034ab57600080fd5b815160ff811681146200307257600080fd5b60ff8416815260ff83166020820152606060408201526000620025ea606083018462003314565b600060208284031215620034f757600080fd5b815167ffffffffffffffff8111156200350f57600080fd5b8201601f810184136200352157600080fd5b80516200353262002f0a8262002e9e565b8181528560208385010111156200354857600080fd5b620025ea826020830160208601620032ee565b60208152600062001dfe602083018462003314565b600067ffffffffffffffff8211156200358d576200358d62002df0565b5060051b60200190565b600082601f830112620035a957600080fd5b81356020620035bc62002f0a8362003570565b82815260059290921b84018101918181019086841115620035dc57600080fd5b8286015b84811015620035f95780358352918301918301620035e0565b509695505050505050565b801515811462001ca257600080fd5b803562002ca78162003604565b80356fffffffffffffffffffffffffffffffff8116811462002ca757600080fd5b80356bffffffffffffffffffffffff8116811462002ca757600080fd5b600082601f8301126200367057600080fd5b813560206200368362002f0a8362003570565b8281526101209283028501820192828201919087851115620036a457600080fd5b8387015b858110156200377e5781818a031215620036c25760008081fd5b620036cc62002e1f565b620036d78262003613565b8152620036e686830162003613565b868201526040620036f981840162002dcb565b9082015260606200370c83820162002dcb565b9082015260806200371f83820162002c9a565b9082015260a06200373283820162003620565b9082015260c06200374583820162003641565b9082015260e06200375883820162002dcb565b908201526101006200376c83820162002c9a565b908201528452928401928101620036a8565b5090979650505050505050565b600082601f8301126200379d57600080fd5b81356020620037b062002f0a8362003570565b82815260059290921b84018101918181019086841115620037d057600080fd5b8286015b84811015620035f9578035620037ea8162002c77565b8352918301918301620037d4565b600082601f8301126200380a57600080fd5b813560206200381d62002f0a8362003570565b82815260059290921b840181019181810190868411156200383d57600080fd5b8286015b84811015620035f957803567ffffffffffffffff811115620038635760008081fd5b620038738986838b010162002ee7565b84525091830191830162003841565b600080600080600080600060e0888a0312156200389e57600080fd5b873567ffffffffffffffff80821115620038b757600080fd5b620038c58b838c0162003597565b985060208a0135915080821115620038dc57600080fd5b620038ea8b838c016200365e565b975060408a01359150808211156200390157600080fd5b6200390f8b838c016200378b565b965060608a01359150808211156200392657600080fd5b620039348b838c016200378b565b955060808a01359150808211156200394b57600080fd5b620039598b838c01620037f8565b945060a08a01359150808211156200397057600080fd5b6200397e8b838c01620037f8565b935060c08a01359150808211156200399557600080fd5b50620039a48a828b01620037f8565b91505092959891949750929550565b600063ffffffff808316818103620039cf57620039cf620030d7565b6001019392505050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b60006020828403121562003a3957600080fd5b5051919050565b6bffffffffffffffffffffffff828116828216039080821115620029865762002986620030d7565b601f82111562001d3457600081815260208120601f850160051c8101602086101562003a915750805b601f850160051c820191505b8181101562003ab25782815560010162003a9d565b505050505050565b815167ffffffffffffffff81111562003ad75762003ad762002df0565b62003aef8162003ae8845462003132565b8462003a68565b602080601f83116001811462003b45576000841562003b0e5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855562003ab2565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101562003b945788860151825594840194600190910190840162003b73565b508582101562003bd157878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8051602080830151919081101562003181577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60209190910360031b1b16919050565b60006020828403121562003c3757600080fd5b8151620030728162003604565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000825162003c87818460208701620032ee565b919091019291505056fe60c060405234801561001057600080fd5b506040516103ca3803806103ca83398101604081905261002f91610076565b600080546001600160a01b0319166001600160a01b039384161790559181166080521660a0526100b9565b80516001600160a01b038116811461007157600080fd5b919050565b60008060006060848603121561008b57600080fd5b6100948461005a565b92506100a26020850161005a565b91506100b06040850161005a565b90509250925092565b60805160a0516102e76100e36000396000603801526000818160c4015261011701526102e76000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806379188d161461007b578063f00e6a2a146100aa575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e808015610076573d6000f35b3d6000fd5b61008e6100893660046101c1565b6100ee565b6040805192151583526020830191909152015b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100a1565b60008054819073ffffffffffffffffffffffffffffffffffffffff16331461011557600080fd5b7f00000000000000000000000000000000000000000000000000000000000000005a91505a61138881101561014957600080fd5b61138881039050856040820482031161016157600080fd5b50803b61016d57600080fd5b6000808551602087016000858af192505a610188908361029a565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080604083850312156101d457600080fd5b82359150602083013567ffffffffffffffff808211156101f357600080fd5b818501915085601f83011261020757600080fd5b81358181111561021957610219610192565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561025f5761025f610192565b8160405282815288602084870101111561027857600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b818103818111156102d4577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea164736f6c6343000813000aa164736f6c6343000813000a", + Bin: "0x6101806040523480156200001257600080fd5b50604051620047913803806200479183398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e0516101005161012051610140516101605161407d62000714600039600081816088015260de01526000505060005050600081816111d201526114eb01526000505060005050600050506000505061407d6000f3fe608060405260043610620000865760003560e01c80638e86139b11620000555780638e86139b1462000192578063c62cf68414620001b7578063c804802214620001eb578063f2fde38b14620002105762000086565b8063349e8cca14620000ce57806379ba5097146200012857806385c1b0ba14620001405780638da5cb5b1462000165575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e808015620000c7573d6000f35b3d6000fd5b005b348015620000db57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156200013557600080fd5b50620000cc62000235565b3480156200014d57600080fd5b50620000cc6200015f36600462002cc1565b62000338565b3480156200017257600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16620000fe565b3480156200019f57600080fd5b50620000cc620001b136600462002d9a565b62001095565b348015620001c457600080fd5b50620001dc620001d636600462002f58565b6200141d565b6040519081526020016200011f565b348015620001f857600080fd5b50620000cc6200020a3660046200304d565b620017ca565b3480156200021d57600080fd5b50620000cc6200022f36600462003067565b62001ca2565b60015473ffffffffffffffffffffffffffffffffffffffff163314620002bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b600173ffffffffffffffffffffffffffffffffffffffff82166000908152601c602052604090205460ff1660038111156200037757620003776200308e565b14158015620003c35750600373ffffffffffffffffffffffffffffffffffffffff82166000908152601c602052604090205460ff166003811115620003c057620003c06200308e565b14155b15620003fb576040517f0ebeec3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60165473ffffffffffffffffffffffffffffffffffffffff166200044b576040517fd12d7d8d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082900362000487576040517f2c2fc94100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290528190819060008667ffffffffffffffff811115620004f157620004f162002e05565b6040519080825280602002602001820160405280156200051b578160200160208202803683370190505b50905060008767ffffffffffffffff8111156200053c576200053c62002e05565b604051908082528060200260200182016040528015620005d357816020015b604080516101208101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e0820181905261010082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816200055b5790505b50905060008867ffffffffffffffff811115620005f457620005f462002e05565b6040519080825280602002602001820160405280156200062957816020015b6060815260200190600190039081620006135790505b50905060008967ffffffffffffffff8111156200064a576200064a62002e05565b6040519080825280602002602001820160405280156200067f57816020015b6060815260200190600190039081620006695790505b50905060008a67ffffffffffffffff811115620006a057620006a062002e05565b604051908082528060200260200182016040528015620006d557816020015b6060815260200190600190039081620006bf5790505b50905060005b8b81101562000e04578c8c82818110620006f957620006f9620030bd565b602090810292909201356000818152600484526040808220815161012081018352815460ff8082161515835261010080830490911615159883019890985263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e082015260029091015490911694810194909452909a5091985050819003620008305786610100015199508660c001516bffffffffffffffffffffffff1698505b8973ffffffffffffffffffffffffffffffffffffffff1687610100015173ffffffffffffffffffffffffffffffffffffffff1614620008f55773ffffffffffffffffffffffffffffffffffffffff8a166000908152602160205260409020546200089c908a906200311b565b73ffffffffffffffffffffffffffffffffffffffff8b16600081815260216020526040902091909155620008d2908c8b62001cba565b86610100015199508660c001516bffffffffffffffffffffffff1698506200091e565b80156200091e5760c08701516200091b906bffffffffffffffffffffffff168a62003131565b98505b620009298862001d4e565b60808701516040517f1a5da6c800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8d8116600483015290911690631a5da6c890602401600060405180830381600087803b1580156200099957600080fd5b505af1158015620009ae573d6000803e3d6000fd5b5050505086858281518110620009c857620009c8620030bd565b60200260200101819052506005600089815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1686828151811062000a1c5762000a1c620030bd565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091018201526000898152600790915260409020805462000a5b9062003147565b80601f016020809104026020016040519081016040528092919081815260200182805462000a899062003147565b801562000ada5780601f1062000aae5761010080835404028352916020019162000ada565b820191906000526020600020905b81548152906001019060200180831162000abc57829003601f168201915b505050505084828151811062000af45762000af4620030bd565b6020026020010181905250601d6000898152602001908152602001600020805462000b1f9062003147565b80601f016020809104026020016040519081016040528092919081815260200182805462000b4d9062003147565b801562000b9e5780601f1062000b725761010080835404028352916020019162000b9e565b820191906000526020600020905b81548152906001019060200180831162000b8057829003601f168201915b505050505083828151811062000bb85762000bb8620030bd565b6020026020010181905250601e6000898152602001908152602001600020805462000be39062003147565b80601f016020809104026020016040519081016040528092919081815260200182805462000c119062003147565b801562000c625780601f1062000c365761010080835404028352916020019162000c62565b820191906000526020600020905b81548152906001019060200180831162000c4457829003601f168201915b505050505082828151811062000c7c5762000c7c620030bd565b602090810291909101810191909152600089815260048252604080822080547fffff0000000000000000000000000000000000000000000000000000000000001681556001810183905560020180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055600790925290812062000d029162002c24565b6000888152601d6020526040812062000d1b9162002c24565b6000888152601e6020526040812062000d349162002c24565b600088815260066020908152604080832080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811690915560059092529091208054909116905562000d8a60028962001e05565b5060c0870151604080516bffffffffffffffffffffffff909216825273ffffffffffffffffffffffffffffffffffffffff8d16602083015289917fb38647142fbb1ea4c000fc4569b37a4e9a9f6313317b84ee3e5326c1a6cd06ff910160405180910390a28062000dfb816200319c565b915050620006db565b5073ffffffffffffffffffffffffffffffffffffffff891660009081526021602052604090205462000e389089906200311b565b73ffffffffffffffffffffffffffffffffffffffff8a1660008181526021602052604090209190915562000e6e908b8a62001cba565b60008c8c868167ffffffffffffffff81111562000e8f5762000e8f62002e05565b60405190808252806020026020018201604052801562000eb9578160200160208202803683370190505b508988888860405160200162000ed7989796959493929190620033ce565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282526016547faab9edd6000000000000000000000000000000000000000000000000000000008452915190935073ffffffffffffffffffffffffffffffffffffffff808f1693638e86139b939091169163c71249ab91600491869163aab9edd6918482019160209190819003860181865afa15801562000f87573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000fad9190620034ad565b866040518463ffffffff1660e01b815260040162000fce93929190620034d2565b600060405180830381865afa15801562000fec573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052620010349190810190620034f9565b6040518263ffffffff1660e01b815260040162001052919062003570565b600060405180830381600087803b1580156200106d57600080fd5b505af115801562001082573d6000803e3d6000fd5b5050505050505050505050505050505050565b6002336000908152601c602052604090205460ff166003811115620010be57620010be6200308e565b14158015620010f457506003336000908152601c602052604090205460ff166003811115620010f157620010f16200308e565b14155b156200112c576040517f0ebeec3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080808080808062001142888a018a62003897565b965096509650965096509650965060005b87518110156200141157600073ffffffffffffffffffffffffffffffffffffffff168782815181106200118a576200118a620030bd565b60200260200101516080015173ffffffffffffffffffffffffffffffffffffffff16036200129e57858181518110620011c757620011c7620030bd565b6020026020010151307f0000000000000000000000000000000000000000000000000000000000000000604051620011ff9062002c63565b73ffffffffffffffffffffffffffffffffffffffff938416815291831660208301529091166040820152606001604051809103906000f08015801562001249573d6000803e3d6000fd5b508782815181106200125f576200125f620030bd565b60200260200101516080019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b62001356888281518110620012b757620012b7620030bd565b6020026020010151888381518110620012d457620012d4620030bd565b6020026020010151878481518110620012f157620012f1620030bd565b60200260200101518785815181106200130e576200130e620030bd565b60200260200101518786815181106200132b576200132b620030bd565b6020026020010151878781518110620013485762001348620030bd565b602002602001015162001e1c565b8781815181106200136b576200136b620030bd565b60200260200101517f74931a144e43a50694897f241d973aecb5024c0e910f9bb80a163ea3c1cf5a71888381518110620013a957620013a9620030bd565b602002602001015160c0015133604051620013f49291906bffffffffffffffffffffffff92909216825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b60405180910390a28062001408816200319c565b91505062001153565b50505050505050505050565b6000805473ffffffffffffffffffffffffffffffffffffffff1633148015906200145157506200144f60093362002339565b155b1562001489576040517fd48b678b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a163b620014d8576040517f09ee12d500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620014e38762002369565b905060008a307f0000000000000000000000000000000000000000000000000000000000000000604051620015189062002c63565b73ffffffffffffffffffffffffffffffffffffffff938416815291831660208301529091166040820152606001604051809103906000f08015801562001562573d6000803e3d6000fd5b50905062001653826040518061012001604052806000151581526020016000151581526020018d63ffffffff16815260200163ffffffff801681526020018473ffffffffffffffffffffffffffffffffffffffff16815260200160006fffffffffffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff168152602001600063ffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff168152508b89898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b92508a915062001e1c9050565b601680547c0100000000000000000000000000000000000000000000000000000000900463ffffffff1690601c6200168b83620039c8565b91906101000a81548163ffffffff021916908363ffffffff16021790555050817fbae366358c023f887e791d7a62f2e4316f1026bd77f6fb49501a917b3bc5d0128b8b6040516200170492919063ffffffff92909216825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b60405180910390a2817fcba2d5723b2ee59e53a8e8a82a4a7caf4fdfe70e9f7c582950bf7e7a5c24e83d878760405162001740929190620039ee565b60405180910390a2817f2b72ac786c97e68dbab71023ed6f2bdbfc80ad9bb7808941929229d71b7d5664856040516200177a919062003570565b60405180910390a2817f3e8740446213c8a77d40e08f79136ce3f347d13ed270a6ebdf57159e0faf485084604051620017b4919062003570565b60405180910390a2509998505050505050505050565b6000818152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e08201526002909101549091169181019190915290620018ee60005473ffffffffffffffffffffffffffffffffffffffff1690565b61010083015173ffffffffffffffffffffffffffffffffffffffff90811660009081526022602090815260408083206002015460155482517f57e871e70000000000000000000000000000000000000000000000000000000081529251968616331497506bffffffffffffffffffffffff90911695939416926357e871e7926004808401939192918290030181865afa15801562001990573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620019b6919062003a3b565b9050836060015163ffffffff16600003620019fd576040517ffbc0357800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606084015163ffffffff9081161462001a42576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8215801562001a75575060008581526005602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b1562001aad576040517ffbdb8e5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8262001ac35762001ac060328262003131565b90505b6000858152600460205260409020805463ffffffff8084166601000000000000027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff9092169190911790915562001b2090600290879062001e0516565b506000826bffffffffffffffffffffffff168560a001516fffffffffffffffffffffffffffffffff16101562001b935760a085015162001b61908462003a55565b90508460c001516bffffffffffffffffffffffff16816bffffffffffffffffffffffff16111562001b93575060c08401515b808560c0015162001ba5919062003a55565b600087815260046020908152604080832060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000006bffffffffffffffffffffffff9687160217905561010089015173ffffffffffffffffffffffffffffffffffffffff168352602190915290205462001c37918316906200311b565b61010086015173ffffffffffffffffffffffffffffffffffffffff1660009081526021602052604080822092909255905167ffffffffffffffff84169188917f91cb3bb75cfbd718bbfccc56b7f53d92d7048ef4ca39a3b7b7c6d4af1f7911819190a3505050505050565b62001cac62002608565b62001cb7816200268d565b50565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905262001d4990849062002784565b505050565b60008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff16331462001dac576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020546601000000000000900463ffffffff9081161462001cb7576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600062001e13838362002897565b90505b92915050565b601454760100000000000000000000000000000000000000000000900460ff161562001e74576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60175483517c010000000000000000000000000000000000000000000000000000000090910463ffffffff16101562001ed9576040517fae7235df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108fc856040015163ffffffff16108062001f1f5750601654604086015163ffffffff780100000000000000000000000000000000000000000000000090920482169116115b1562001f57576040517f14c237fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000868152600460205260409020546a0100000000000000000000900473ffffffffffffffffffffffffffffffffffffffff161562001fc2576040517f6e3b930b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010085015173ffffffffffffffffffffffffffffffffffffffff90811660009081526022602052604090205467010000000000000090041662002032576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846004600088815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555060408201518160000160026101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160066101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600a6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160010160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160010160106101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050836005600088815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260076000888152602001908152602001600020908162002277919062003acf565b5060c085015161010086015173ffffffffffffffffffffffffffffffffffffffff16600090815260216020526040902054620022c2916bffffffffffffffffffffffff169062003131565b61010086015173ffffffffffffffffffffffffffffffffffffffff16600090815260216020908152604080832093909355888252601d90522062002307838262003acf565b506000868152601e6020526040902062002322828262003acf565b5062002330600287620029a2565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151562001e13565b601554604080517f57e871e70000000000000000000000000000000000000000000000000000000081529051600092839273ffffffffffffffffffffffffffffffffffffffff90911691839183916385df51fd9160019184916357e871e79160048083019260209291908290030181865afa158015620023ed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002413919062003a3b565b6200241f91906200311b565b6040518263ffffffff1660e01b81526004016200243e91815260200190565b602060405180830381865afa1580156200245c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002482919062003a3b565b60165460408051602081019390935230908301527c0100000000000000000000000000000000000000000000000000000000900463ffffffff166060820152608001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083015201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060045b600f811015620025965783828281518110620025525762002552620030bd565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806200258d816200319c565b91505062002532565b50846001811115620025ac57620025ac6200308e565b60f81b81600f81518110620025c557620025c5620030bd565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350620025ff8162003bf6565b95945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146200268b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401620002b3565b565b3373ffffffffffffffffffffffffffffffffffffffff8216036200270e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620002b3565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000620027e8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16620029b09092919063ffffffff16565b80519091501562001d49578080602001905181019062002809919062003c39565b62001d49576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401620002b3565b6000818152600183016020526040812054801562002990576000620028be6001836200311b565b8554909150600090620028d4906001906200311b565b905081811462002940576000866000018281548110620028f857620028f8620030bd565b90600052602060002001549050808760000184815481106200291e576200291e620030bd565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062002954576200295462003c59565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062001e16565b600091505062001e16565b5092915050565b600062001e138383620029c9565b6060620029c1848460008562002a1b565b949350505050565b600081815260018301602052604081205462002a125750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562001e16565b50600062001e16565b60608247101562002aaf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401620002b3565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405162002ada919062003c88565b60006040518083038185875af1925050503d806000811462002b19576040519150601f19603f3d011682016040523d82523d6000602084013e62002b1e565b606091505b509150915062002b318783838762002b3c565b979650505050505050565b6060831562002bd757825160000362002bcf5773ffffffffffffffffffffffffffffffffffffffff85163b62002bcf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620002b3565b5081620029c1565b620029c1838381511562002bee5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002b3919062003570565b50805462002c329062003147565b6000825580601f1062002c43575050565b601f01602090049060005260206000209081019062001cb7919062002c71565b6103ca8062003ca783390190565b5b8082111562002c88576000815560010162002c72565b5090565b73ffffffffffffffffffffffffffffffffffffffff8116811462001cb757600080fd5b803562002cbc8162002c8c565b919050565b60008060006040848603121562002cd757600080fd5b833567ffffffffffffffff8082111562002cf057600080fd5b818601915086601f83011262002d0557600080fd5b81358181111562002d1557600080fd5b8760208260051b850101111562002d2b57600080fd5b6020928301955093505084013562002d438162002c8c565b809150509250925092565b60008083601f84011262002d6157600080fd5b50813567ffffffffffffffff81111562002d7a57600080fd5b60208301915083602082850101111562002d9357600080fd5b9250929050565b6000806020838503121562002dae57600080fd5b823567ffffffffffffffff81111562002dc657600080fd5b62002dd48582860162002d4e565b90969095509350505050565b803563ffffffff8116811462002cbc57600080fd5b80356002811062002cbc57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171562002e5b5762002e5b62002e05565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171562002eab5762002eab62002e05565b604052919050565b600067ffffffffffffffff82111562002ed05762002ed062002e05565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011262002f0e57600080fd5b813562002f2562002f1f8262002eb3565b62002e61565b81815284602083860101111562002f3b57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060008060006101008a8c03121562002f7857600080fd5b62002f838a62002caf565b985062002f9360208b0162002de0565b975062002fa360408b0162002caf565b965062002fb360608b0162002df5565b955062002fc360808b0162002caf565b945060a08a013567ffffffffffffffff8082111562002fe157600080fd5b62002fef8d838e0162002d4e565b909650945060c08c01359150808211156200300957600080fd5b620030178d838e0162002efc565b935060e08c01359150808211156200302e57600080fd5b506200303d8c828d0162002efc565b9150509295985092959850929598565b6000602082840312156200306057600080fd5b5035919050565b6000602082840312156200307a57600080fd5b8135620030878162002c8c565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111562001e165762001e16620030ec565b8082018082111562001e165762001e16620030ec565b600181811c908216806200315c57607f821691505b60208210810362003196577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620031d057620031d0620030ec565b5060010190565b600081518084526020808501945080840160005b83811015620032b05781518051151588528381015115158489015260408082015163ffffffff908116918a01919091526060808301518216908a015260808083015173ffffffffffffffffffffffffffffffffffffffff908116918b019190915260a0808401516fffffffffffffffffffffffffffffffff16908b015260c0808401516bffffffffffffffffffffffff16908b015260e080840151909216918a01919091526101009182015116908801526101209096019590820190600101620031eb565b509495945050505050565b600081518084526020808501945080840160005b83811015620032b057815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101620032cf565b60005b838110156200332057818101518382015260200162003306565b50506000910152565b600081518084526200334381602086016020860162003303565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b85811015620033c1578284038952620033ae84835162003329565b9885019893509084019060010162003393565b5091979650505050505050565b60e081528760e082015260006101007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8a11156200340b57600080fd5b8960051b808c838601378301838103820160208501526200342f8282018b620031d7565b9150508281036040840152620034468189620032bb565b905082810360608401526200345c8188620032bb565b9050828103608084015262003472818762003375565b905082810360a084015262003488818662003375565b905082810360c08401526200349e818562003375565b9b9a5050505050505050505050565b600060208284031215620034c057600080fd5b815160ff811681146200308757600080fd5b60ff8416815260ff83166020820152606060408201526000620025ff606083018462003329565b6000602082840312156200350c57600080fd5b815167ffffffffffffffff8111156200352457600080fd5b8201601f810184136200353657600080fd5b80516200354762002f1f8262002eb3565b8181528560208385010111156200355d57600080fd5b620025ff82602083016020860162003303565b60208152600062001e13602083018462003329565b600067ffffffffffffffff821115620035a257620035a262002e05565b5060051b60200190565b600082601f830112620035be57600080fd5b81356020620035d162002f1f8362003585565b82815260059290921b84018101918181019086841115620035f157600080fd5b8286015b848110156200360e5780358352918301918301620035f5565b509695505050505050565b801515811462001cb757600080fd5b803562002cbc8162003619565b80356fffffffffffffffffffffffffffffffff8116811462002cbc57600080fd5b80356bffffffffffffffffffffffff8116811462002cbc57600080fd5b600082601f8301126200368557600080fd5b813560206200369862002f1f8362003585565b8281526101209283028501820192828201919087851115620036b957600080fd5b8387015b85811015620037935781818a031215620036d75760008081fd5b620036e162002e34565b620036ec8262003628565b8152620036fb86830162003628565b8682015260406200370e81840162002de0565b9082015260606200372183820162002de0565b9082015260806200373483820162002caf565b9082015260a06200374783820162003635565b9082015260c06200375a83820162003656565b9082015260e06200376d83820162002de0565b908201526101006200378183820162002caf565b908201528452928401928101620036bd565b5090979650505050505050565b600082601f830112620037b257600080fd5b81356020620037c562002f1f8362003585565b82815260059290921b84018101918181019086841115620037e557600080fd5b8286015b848110156200360e578035620037ff8162002c8c565b8352918301918301620037e9565b600082601f8301126200381f57600080fd5b813560206200383262002f1f8362003585565b82815260059290921b840181019181810190868411156200385257600080fd5b8286015b848110156200360e57803567ffffffffffffffff811115620038785760008081fd5b620038888986838b010162002efc565b84525091830191830162003856565b600080600080600080600060e0888a031215620038b357600080fd5b873567ffffffffffffffff80821115620038cc57600080fd5b620038da8b838c01620035ac565b985060208a0135915080821115620038f157600080fd5b620038ff8b838c0162003673565b975060408a01359150808211156200391657600080fd5b620039248b838c01620037a0565b965060608a01359150808211156200393b57600080fd5b620039498b838c01620037a0565b955060808a01359150808211156200396057600080fd5b6200396e8b838c016200380d565b945060a08a01359150808211156200398557600080fd5b620039938b838c016200380d565b935060c08a0135915080821115620039aa57600080fd5b50620039b98a828b016200380d565b91505092959891949750929550565b600063ffffffff808316818103620039e457620039e4620030ec565b6001019392505050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b60006020828403121562003a4e57600080fd5b5051919050565b6bffffffffffffffffffffffff8281168282160390808211156200299b576200299b620030ec565b601f82111562001d4957600081815260208120601f850160051c8101602086101562003aa65750805b601f850160051c820191505b8181101562003ac75782815560010162003ab2565b505050505050565b815167ffffffffffffffff81111562003aec5762003aec62002e05565b62003b048162003afd845462003147565b8462003a7d565b602080601f83116001811462003b5a576000841562003b235750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855562003ac7565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101562003ba95788860151825594840194600190910190840162003b88565b508582101562003be657878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8051602080830151919081101562003196577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60209190910360031b1b16919050565b60006020828403121562003c4c57600080fd5b8151620030878162003619565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000825162003c9c81846020870162003303565b919091019291505056fe60c060405234801561001057600080fd5b506040516103ca3803806103ca83398101604081905261002f91610076565b600080546001600160a01b0319166001600160a01b039384161790559181166080521660a0526100b9565b80516001600160a01b038116811461007157600080fd5b919050565b60008060006060848603121561008b57600080fd5b6100948461005a565b92506100a26020850161005a565b91506100b06040850161005a565b90509250925092565b60805160a0516102e76100e36000396000603801526000818160c4015261011701526102e76000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806379188d161461007b578063f00e6a2a146100aa575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e808015610076573d6000f35b3d6000fd5b61008e6100893660046101c1565b6100ee565b6040805192151583526020830191909152015b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100a1565b60008054819073ffffffffffffffffffffffffffffffffffffffff16331461011557600080fd5b7f00000000000000000000000000000000000000000000000000000000000000005a91505a61138881101561014957600080fd5b61138881039050856040820482031161016157600080fd5b50803b61016d57600080fd5b6000808551602087016000858af192505a610188908361029a565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080604083850312156101d457600080fd5b82359150602083013567ffffffffffffffff808211156101f357600080fd5b818501915085601f83011261020757600080fd5b81358181111561021957610219610192565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561025f5761025f610192565b8160405282815288602084870101111561027857600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b818103818111156102d4577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea164736f6c6343000813000aa164736f6c6343000813000a", } var AutomationRegistryLogicAABI = AutomationRegistryLogicAMetaData.ABI diff --git a/core/gethwrappers/generated/automation_registry_wrapper_2_3/automation_registry_wrapper_2_3.go b/core/gethwrappers/generated/automation_registry_wrapper_2_3/automation_registry_wrapper_2_3.go index 1edcb07dc6f..29bfe3155f5 100644 --- a/core/gethwrappers/generated/automation_registry_wrapper_2_3/automation_registry_wrapper_2_3.go +++ b/core/gethwrappers/generated/automation_registry_wrapper_2_3/automation_registry_wrapper_2_3.go @@ -65,7 +65,7 @@ type AutomationRegistryBase23OnchainConfig struct { var AutomationRegistryMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"contractAutomationRegistryLogicA2_3\",\"name\":\"logicA\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contractIERC20Metadata\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfigBytes\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"contractIChainModule\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"onchainConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig[]\",\"name\":\"billingConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConfigTypeSafe\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101806040523480156200001257600080fd5b506040516200668a3803806200668a83398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e05161010051610120516101405161016051615f56620007346000396000818160be01526101910152600050506000505060005050600050506000613b1701526000505060008181610de701528181610ef5015281816110200152818161106a015281816116ec01526131400152615f566000f3fe6080604052600436106100bc5760003560e01c80638da5cb5b11610074578063b1dc65a41161004e578063b1dc65a4146102f6578063e3d0e71214610316578063f2fde38b14610336576100bc565b80638da5cb5b14610265578063a4c0ed3614610290578063afcb95d7146102b0576100bc565b8063349e8cca116100a5578063349e8cca1461018257806379ba5097146101d657806381ff7048146101eb576100bc565b80630870d3a114610103578063181f5a7714610123575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156100fc573d6000f35b3d6000fd5b005b34801561010f57600080fd5b5061010161011e366004614c9d565b610356565b34801561012f57600080fd5b5061016c6040518060400160405280601881526020017f4175746f6d6174696f6e526567697374727920322e332e30000000000000000081525081565b6040516101799190614e19565b60405180910390f35b34801561018e57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610179565b3480156101e257600080fd5b50610101610ccd565b3480156101f757600080fd5b5061024260175460135463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610179565b34801561027157600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101b1565b34801561029c57600080fd5b506101016102ab366004614e75565b610dcf565b3480156102bc57600080fd5b50601354601454604080516000815260208101939093526c0100000000000000000000000090910463ffffffff1690820152606001610179565b34801561030257600080fd5b50610101610311366004614f16565b6110eb565b34801561032257600080fd5b50610101610331366004614fcd565b6113cc565b34801561034257600080fd5b5061010161035136600461509a565b611406565b61035e61141a565b601f8851111561039a576040517f25d0209c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560ff166000036103d7576040517fe77dba5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b865188511415806103f657506103ee8660036150e6565b60ff16885111155b1561042d576040517f1d2d1c5800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051825114610468576040517fcf54c06a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610472828261149d565b61047c8888611ad5565b604051806101200160405280601460000160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff168152602001600063ffffffff1681526020018660a0015162ffffff16815260200186610120015161ffff1681526020018760ff168152602001601460000160169054906101000a900460ff1615158152602001601460000160179054906101000a900460ff1615158152602001866080015115158152602001866101e0015173ffffffffffffffffffffffffffffffffffffffff16815250601460008201518160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550602082015181600001600c6101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160106101000a81548162ffffff021916908362ffffff16021790555060608201518160000160136101000a81548161ffff021916908361ffff16021790555060808201518160000160156101000a81548160ff021916908360ff16021790555060a08201518160000160166101000a81548160ff02191690831515021790555060c08201518160000160176101000a81548160ff02191690831515021790555060e08201518160000160186101000a81548160ff0219169083151502179055506101008201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050604051806101600160405280866060015173ffffffffffffffffffffffffffffffffffffffff168152602001866000015163ffffffff168152602001866020015163ffffffff1681526020016016600001601c9054906101000a900463ffffffff1663ffffffff16815260200186610100015173ffffffffffffffffffffffffffffffffffffffff168152602001601660010160149054906101000a900463ffffffff1663ffffffff168152602001601660010160189054906101000a900463ffffffff1663ffffffff168152602001866040015163ffffffff16815260200186610140015173ffffffffffffffffffffffffffffffffffffffff1681526020018660c0015163ffffffff1681526020018660e0015163ffffffff16815250601660008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101208201518160020160146101000a81548163ffffffff021916908363ffffffff1602179055506101408201518160020160186101000a81548163ffffffff021916908363ffffffff160217905550905050846101600151601981905550846101800151601a81905550846101a00151601b819055506000601660010160189054906101000a900463ffffffff169050856101e0015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa69190615102565b601780547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000063ffffffff9384160217808255600192601491610b1d9185917401000000000000000000000000000000000000000090041661511b565b92506101000a81548163ffffffff021916908363ffffffff160217905550600086604051602001610b4e9190615189565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152919052601754909150610bb3904690309074010000000000000000000000000000000000000000900463ffffffff168d8d8d878d8d612196565b6013556000610bc26009612240565b90505b8015610bff57610bec610be4610bdc60018461530f565b600990612250565b600990612263565b5080610bf781615322565b915050610bc5565b5060005b876101c0015151811015610c5657610c43886101c001518281518110610c2b57610c2b615357565b6020026020010151600961228590919063ffffffff16565b5080610c4e81615386565b915050610c03565b506013546017546040517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0592610cb99286927401000000000000000000000000000000000000000090910463ffffffff16908f908f908f9089908f908f906153be565b60405180910390a150505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610d53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610e3e576040517fc8bad78d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208114610e78576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610e8682840184615454565b6000818152600460205260409020549091506601000000000000900463ffffffff90811614610ee1576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020600201547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614610f65576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260046020526040902060010154610fa490859070010000000000000000000000000000000090046bffffffffffffffffffffffff1661546d565b600082815260046020908152604080832060010180546bffffffffffffffffffffffff95909516700100000000000000000000000000000000027fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff9095169490941790935573ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168252602190522054611053908590615492565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660009081526021602090815260409182902093909355516bffffffffffffffffffffffff871681529087169183917fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa734891506203910160405180910390a35050505050565b60005a60408051610120810182526014546bffffffffffffffffffffffff8116825263ffffffff6c01000000000000000000000000820416602083015262ffffff7001000000000000000000000000000000008204169282019290925261ffff730100000000000000000000000000000000000000830416606082015260ff75010000000000000000000000000000000000000000008304811660808301527601000000000000000000000000000000000000000000008304811615801560a08401527701000000000000000000000000000000000000000000000084048216151560c0840152780100000000000000000000000000000000000000000000000090930416151560e082015260155473ffffffffffffffffffffffffffffffffffffffff1661010082015291925061124f576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600b602052604090205460ff16611298576040517f1099ed7500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6013548a35146112d4576040517fdfdcf8e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60808101516112e49060016154a5565b60ff16861415806112f55750858414155b1561132c576040517f0244f71a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61133c8a8a8a8a8a8a8a8a6122a7565b60006113488a8a612510565b905060208b0135600881901c63ffffffff166113658484876125c9565b836020015163ffffffff168163ffffffff1611156113bd57601480547fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff166c0100000000000000000000000063ffffffff8416021790555b50505050505050505050505050565b6000806000858060200190518101906113e5919061568f565b9250925092506113fb8989898689898888610356565b505050505050505050565b61140e61141a565b611417816131b6565b50565b60005473ffffffffffffffffffffffffffffffffffffffff16331461149b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610d4a565b565b60005b60245481101561155b5760226000602483815481106114c1576114c1615357565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181019190915560020180547fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001690558061155381615386565b9150506114a0565b50611568602460006146f1565b60255460ff1660005b8351811015611acf57600084828151811061158e5761158e615357565b6020026020010151905060008483815181106115ac576115ac615357565b602002602001015190508173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611601573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611625919061583a565b60ff16816060015160ff161415806116b35750806040015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611687573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ab919061583a565b60ff16600814155b156116ea576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480156117565750600184600181111561175457611754615857565b145b1561178d576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821615806117c85750604081015173ffffffffffffffffffffffffffffffffffffffff16155b156117ff576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82811660009081526022602052604090205467010000000000000090041615611869576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6024805460018181019092557f7cd332d19b93bcabe3cce7ca0c18a052f57e5fd03b4758a09f30f5ddc4b22ec401805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216821790925560008181526022602090815260409182902086518154928801518489015160608a015160ff167b01000000000000000000000000000000000000000000000000000000027fffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffff9190981667010000000000000002167fffffffff000000000000000000000000000000000000000000ffffffffffffff62ffffff909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000090951663ffffffff9093169290921793909317929092169190911793909317835560808501519383019390935560a0840151600290920180546bffffffffffffffffffffffff9093167fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009093169290921790915590517fca93cbe727c73163ec538f71be6c0a64877d7f1f6dd35d5ca7cbaef3a3e34ba390611ab2908490600060c08201905063ffffffff835116825262ffffff602084015116602083015273ffffffffffffffffffffffffffffffffffffffff604084015116604083015260ff6060840151166060830152608083015160808301526bffffffffffffffffffffffff60a08401511660a083015292915050565b60405180910390a250508080611ac790615386565b915050611571565b50505050565b60005b600e54811015611b4c57611b39600e8281548110611af857611af8615357565b600091825260209091200154601454600e5473ffffffffffffffffffffffffffffffffffffffff909216916bffffffffffffffffffffffff909116906132ab565b5080611b4481615386565b915050611ad8565b5060255460009060ff16815b600e54811015611cbd57600e8181548110611b7557611b75615357565b6000918252602082200154600d805473ffffffffffffffffffffffffffffffffffffffff9092169550600c929184908110611bb257611bb2615357565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168452838201949094526040928301822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690559286168152600b909252902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556001826001811115611c5457611c54615857565b148015611c99575073ffffffffffffffffffffffffffffffffffffffff83166000908152600b60205260409020546201000090046bffffffffffffffffffffffff1615155b15611cab57611ca9600f84612285565b505b80611cb581615386565b915050611b58565b50611cca600d60006146f1565b611cd6600e60006146f1565b6040805160808101825260008082526020820181905291810182905260608101829052905b855181101561216657600c6000878381518110611d1a57611d1a615357565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000205460ff1615611d85576040517f77cea0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16868281518110611daf57611daf615357565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611e04576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806001151581526020018260ff16815250600c6000888481518110611e3557611e35615357565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528181019290925260400160002082518154939092015160ff16610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909316929092171790558451859082908110611edd57611edd615357565b60200260200101519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611f4d576040517f58a70a0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152600b60209081526040918290208251608081018452905460ff80821615801584526101008304909116938301939093526bffffffffffffffffffffffff6201000082048116948301949094526e01000000000000000000000000000090049092166060830152909250612008576040517f6a7281ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180835260ff80831660208086019182526014546bffffffffffffffffffffffff9081166060880190815273ffffffffffffffffffffffffffffffffffffffff8a166000908152600b909352604092839020885181549551948a0151925184166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff939094166201000002929092167fffffffffffff000000000000000000000000000000000000000000000000ffff94909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009095169490941717919091169290921791909117905583600181111561214257612142615857565b0361215457612152600f85612263565b505b8061215e81615386565b915050611cfb565b50845161217a90600d90602088019061470f565b50835161218e90600e90602087019061470f565b505050505050565b6000808a8a8a8a8a8a8a8a8a6040516020016121ba99989796959493929190615886565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179b9a5050505050505050505050565b600061224a825490565b92915050565b600061225c83836134b3565b9392505050565b600061225c8373ffffffffffffffffffffffffffffffffffffffff84166134dd565b600061225c8373ffffffffffffffffffffffffffffffffffffffff84166135d7565b600087876040516122b992919061591b565b6040519081900381206122d0918b9060200161592b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201208383019092526000808452908301819052909250906000805b888110156124a75760018587836020811061233c5761233c615357565b61234991901a601b6154a5565b8c8c8581811061235b5761235b615357565b905060200201358b8b8681811061237457612374615357565b90506020020135604051600081526020016040526040516123b1949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa1580156123d3573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff81166000908152600c602090815290849020838501909452925460ff8082161515808552610100909204169383019390935290955093509050612481576040517f0f4c073700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826020015160080260ff166001901b84019350808061249f90615386565b91505061231f565b50827e01010101010101010101010101010101010101010101010101010101010101841614612502576040517fc103be2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050505050565b6125496040518060c001604052806000815260200160008152602001606081526020016060815260200160608152602001606081525090565b600061255783850185615a1c565b604081015151606082015151919250908114158061257a57508082608001515114155b8061258a5750808260a001515114155b156125c1576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b509392505050565b600082604001515167ffffffffffffffff8111156125e9576125e96147a6565b6040519080825280602002602001820160405280156126b557816020015b6040805161020081018252600060e08201818152610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e0830182905282526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816126075790505b50905060006040518060800160405280600061ffff16815260200160006bffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff16815260200160008152509050600085610100015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612753573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127779190615102565b9050600086610100015173ffffffffffffffffffffffffffffffffffffffff166318b8f6136040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ef9190615102565b905060005b866040015151811015612c7f57600460008860400151838151811061281b5761281b615357565b6020908102919091018101518252818101929092526040908101600020815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e082015260029091015490911691810191909152855186908390811061293e5761293e615357565b6020026020010151600001819052506129738760400151828151811061296657612966615357565b6020026020010151613626565b85828151811061298557612985615357565b60200260200101516060019060018111156129a2576129a2615857565b908160018111156129b5576129b5615857565b81525050612a19876040015182815181106129d2576129d2615357565b602002602001015184896080015184815181106129f1576129f1615357565b6020026020010151888581518110612a0b57612a0b615357565b60200260200101518c6136d1565b868381518110612a2b57612a2b615357565b6020026020010151602001878481518110612a4857612a48615357565b602002602001015160c0018281525082151515158152505050848181518110612a7357612a73615357565b60200260200101516020015115612aa357600184600001818151612a979190615b09565b61ffff16905250612aa8565b612c6d565b612b0e858281518110612abd57612abd615357565b6020026020010151600001516080015188606001518381518110612ae357612ae3615357565b60200260200101518960a001518481518110612b0157612b01615357565b60200260200101516137f0565b868381518110612b2057612b20615357565b6020026020010151604001878481518110612b3d57612b3d615357565b6020026020010151608001828152508215151515815250505087608001516001612b6791906154a5565b612b759060ff166040615b24565b6103a48860a001518381518110612b8e57612b8e615357565b602002602001015151612ba19190615492565b612bab9190615492565b858281518110612bbd57612bbd615357565b602002602001015160a0018181525050848181518110612bdf57612bdf615357565b602002602001015160a0015184606001818151612bfc9190615492565b9052508451859082908110612c1357612c13615357565b60200260200101516080015186612c2a919061530f565b9550612c6d87604001518281518110612c4557612c45615357565b602002602001015184878481518110612c6057612c60615357565b6020026020010151613a0b565b80612c7781615386565b9150506127f4565b50825161ffff16600003612c965750505050505050565b61c800612ca4366010615b24565b5a612caf908861530f565b612cb99190615492565b612cc39190615492565b83519095506123f090612cda9061ffff1687615b6a565b612ce49190615492565b6040805160808101825260008082526020820181905291810182905260608101829052919650612d1389613b10565b905060005b88604001515181101561304f57868181518110612d3757612d37615357565b6020026020010151602001511561303d57801580612dcf575086612d5c60018361530f565b81518110612d6c57612d6c615357565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff16878281518110612da557612da5615357565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff1614155b15612e0357612e008a888381518110612dea57612dea615357565b6020026020010151600001516101000151613bfa565b92505b6000612f218b6040518061012001604052808b8681518110612e2757612e27615357565b60200260200101516080015181526020018c81526020018a606001518c8781518110612e5557612e55615357565b602002602001015160a001518a612e6c9190615b24565b612e769190615b6a565b81526020018d6000015181526020018d6020015181526020018681526020018b8681518110612ea757612ea7615357565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff168152602001878152602001600115158152508c604001518581518110612ef657612ef6615357565b60200260200101518b8681518110612f1057612f10615357565b602002602001015160000151613d76565b9050806060015187604001818151612f39919061546d565b6bffffffffffffffffffffffff169052506040810151602088018051612f6090839061546d565b6bffffffffffffffffffffffff169052508751889083908110612f8557612f85615357565b60200260200101516040015115158a604001518381518110612fa957612fa9615357565b60200260200101517fad8cc9579b21dfe2c2f6ea35ba15b656e46b4f5b0cb424f52739b8ce5cac9c5b83606001518460400151612fe6919061546d565b8b8681518110612ff857612ff8615357565b6020026020010151608001518d8f60800151888151811061301b5761301b615357565b60200260200101516040516130339493929190615b7e565b60405180910390a3505b8061304781615386565b915050612d18565b505050602083810151336000908152600b9092526040909120805460029061308c9084906201000090046bffffffffffffffffffffffff1661546d565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508260400151601460000160008282829054906101000a90046bffffffffffffffffffffffff166130ea919061546d565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508260400151836020015161312c919061546d565b6bffffffffffffffffffffffff16602160007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546131a89190615492565b909155505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603613235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610d4a565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e01000000000000000000000000000090049091166060820152906134a75760008160600151856133439190615bbb565b905060006133518583615be0565b90508083604001818151613365919061546d565b6bffffffffffffffffffffffff169052506133808582615c0b565b83606001818151613391919061546d565b6bffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff89166000908152600b602090815260409182902087518154928901519389015160608a015186166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff919096166201000002167fffffffffffff000000000000000000000000000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909416939093171792909216179190911790555050505b60400151949350505050565b60008260000182815481106134ca576134ca615357565b9060005260206000200154905092915050565b600081815260018301602052604081205480156135c657600061350160018361530f565b85549091506000906135159060019061530f565b905081811461357a57600086600001828154811061353557613535615357565b906000526020600020015490508087600001848154811061355857613558615357565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061358b5761358b615c3b565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061224a565b600091505061224a565b5092915050565b600081815260018301602052604081205461361e5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561224a565b50600061224a565b6000818160045b600f8110156136b3577fff00000000000000000000000000000000000000000000000000000000000000821683826020811061366b5761366b615357565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146136a157506000949350505050565b806136ab81615386565b91505061362d565b5081600f1a60018111156136c9576136c9615857565b949350505050565b6000808080856060015160018111156136ec576136ec615857565b03613712576136fe8888888888614072565b61370d576000925090506137e6565b61378a565b60018560600151600181111561372a5761372a615857565b0361375857600061373d898989886141fc565b925090508061375257506000925090506137e6565b5061378a565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516060015163ffffffff1687106137df57877fc3237c8807c467c1b39b8d0395eff077313e691bf0a7388106792564ebfd5636876040516137cc9190614e19565b60405180910390a26000925090506137e6565b6001925090505b9550959350505050565b601454600090819077010000000000000000000000000000000000000000000000900460ff161561384d576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b00000000000000000000000000000000000000000000000000000000906138c2908590602401614e19565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d16906139959087908790600401615c6a565b60408051808303816000875af11580156139b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139d79190615c83565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b600081606001516001811115613a2357613a23615857565b03613a8757600083815260046020526040902060010180547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000063ffffffff851602179055505050565b600181606001516001811115613a9f57613a9f615857565b03613b0b5760c08101805160009081526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055915191517fa4a4e334c0e330143f9437484fe516c13bc560b86b5b0daf58e7084aaac228f29190a25b505050565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613b80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ba49190615ccb565b50935050925050600082131580613bba57508042105b80613bea57506000846040015162ffffff16118015613bea5750613bde814261530f565b846040015162ffffff16105b156135d0575050601b5492915050565b60408051608081018252600080825260208083018281528385018381526060850184905273ffffffffffffffffffffffffffffffffffffffff878116855260229093528584208054640100000000810462ffffff1690925263ffffffff82169092527b01000000000000000000000000000000000000000000000000000000810460ff16855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495919484936701000000000000009092049091169163feaf968c9160048083019260a09291908290030181865afa158015613ce7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d0b9190615ccb565b50935050925050600082131580613d2157508042105b80613d5157506000866040015162ffffff16118015613d515750613d45814261530f565b866040015162ffffff16105b15613d655760018301546060850152613d6d565b606084018290525b50505092915050565b604080516080810182526000808252602080830182905292820181905260608201529082015115613def5760008381526023602090815260409182902082518084018452905463ffffffff811680835262ffffff640100000000909204821692840192835260e089018051909401529051915191169101525b6000613dfb8686614409565b60c0840151602082015182519293509091600091613e189161546d565b905082600001516bffffffffffffffffffffffff16826bffffffffffffffffffffffff161015613e9d57819050613e7e87608001518860e0015160600151846bffffffffffffffffffffffff16613e6f9190615b24565b613e799190615b6a565b61464f565b6bffffffffffffffffffffffff16604084015260006060840152613f29565b806bffffffffffffffffffffffff16826bffffffffffffffffffffffff161015613f2957819050613f1583604001516bffffffffffffffffffffffff1688608001518960e0015160600151856bffffffffffffffffffffffff16613f019190615b24565b613f0b9190615b6a565b613e79919061530f565b6bffffffffffffffffffffffff1660608401525b60008681526004602052604090206001018054829190601090613f6f90849070010000000000000000000000000000000090046bffffffffffffffffffffffff16615bbb565b82546101009290920a6bffffffffffffffffffffffff81810219909316918316021790915560008881526004602052604081206001018054928516935091613fca9084906fffffffffffffffffffffffffffffffff16615d1b565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550806bffffffffffffffffffffffff16602160008960c0015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254614061919061530f565b909155509298975050505050505050565b600080848060200190518101906140899190615d44565b845160e00151815191925063ffffffff908116911610156140e657867f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e8866040516140d49190614e19565b60405180910390a260009150506141f3565b8260e0015180156141a657506020810151158015906141a65750602081015161010084015182516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa15801561417f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141a39190615102565b14155b806141b85750805163ffffffff168611155b156141ed57867f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc301866040516140d49190614e19565b60019150505b95945050505050565b6000806000848060200190518101906142159190615d9c565b905060008782600001518360200151846040015160405160200161427794939291909384526020840192909252604083015260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016606082015260640190565b6040516020818303038152906040528051906020012090508460e00151801561435257506080820151158015906143525750608082015161010086015160608401516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa15801561432b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061434f9190615102565b14155b80614367575086826060015163ffffffff1610155b156143b157877f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc3018760405161439c9190614e19565b60405180910390a26000935091506144009050565b60008181526008602052604090205460ff16156143f857877f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e88760405161439c9190614e19565b600193509150505b94509492505050565b60408051608081018252600080825260208201819052918101829052606081019190915260008260e001516000015160ff1690506000846060015161ffff1684606001516144579190615b24565b9050836101000151801561446a5750803a105b1561447257503a5b600060128311614483576001614499565b61448e60128461530f565b61449990600a615f3d565b90506000601284106144ac5760016144c2565b6144b784601261530f565b6144c290600a615f3d565b905060008660a001518760400151886020015189600001516144e49190615492565b6144ee9087615b24565b6144f89190615492565b6145029190615b24565b9050614525828860e001516060015161451b9190615b24565b613e6f8584615b24565b6bffffffffffffffffffffffff168652608087015161454890613e799083615b6a565b6bffffffffffffffffffffffff1660408088019190915260e088015101516000906145819062ffffff16683635c9adc5dea00000615b24565b9050600081633b9aca008a60a001518b60e001516020015163ffffffff168c604001518d600001518b6145b49190615b24565b6145be9190615492565b6145c89190615b24565b6145d29190615b24565b6145dc9190615b6a565b6145e69190615492565b9050614609848a60e00151606001516145ff9190615b24565b613e6f8784615b24565b6bffffffffffffffffffffffff166020890152608089015161462f90613e799083615b6a565b6bffffffffffffffffffffffff1660608901525050505050505092915050565b60006bffffffffffffffffffffffff8211156146ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610d4a565b5090565b50805460008255906000526020600020908101906114179190614791565b828054828255906000526020600020908101928215614789579160200282015b8281111561478957825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061472f565b506146ed9291505b5b808211156146ed5760008155600101614792565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610200810167ffffffffffffffff811182821017156147f9576147f96147a6565b60405290565b60405160c0810167ffffffffffffffff811182821017156147f9576147f96147a6565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614869576148696147a6565b604052919050565b600067ffffffffffffffff82111561488b5761488b6147a6565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff8116811461141757600080fd5b80356148c281614895565b919050565b600082601f8301126148d857600080fd5b813560206148ed6148e883614871565b614822565b82815260059290921b8401810191818101908684111561490c57600080fd5b8286015b8481101561493057803561492381614895565b8352918301918301614910565b509695505050505050565b60ff8116811461141757600080fd5b80356148c28161493b565b63ffffffff8116811461141757600080fd5b80356148c281614955565b801515811461141757600080fd5b80356148c281614972565b62ffffff8116811461141757600080fd5b80356148c28161498b565b61ffff8116811461141757600080fd5b80356148c2816149a7565b600061020082840312156149d557600080fd5b6149dd6147d5565b90506149e882614967565b81526149f660208301614967565b6020820152614a0760408301614967565b6040820152614a18606083016148b7565b6060820152614a2960808301614980565b6080820152614a3a60a0830161499c565b60a0820152614a4b60c08301614967565b60c0820152614a5c60e08301614967565b60e0820152610100614a6f8184016148b7565b90820152610120614a818382016149b7565b90820152610140614a938382016148b7565b90820152610160828101359082015261018080830135908201526101a080830135908201526101c08083013567ffffffffffffffff811115614ad457600080fd5b614ae0858286016148c7565b8284015250506101e0614af48184016148b7565b9082015292915050565b803567ffffffffffffffff811681146148c257600080fd5b600082601f830112614b2757600080fd5b813567ffffffffffffffff811115614b4157614b416147a6565b614b7260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614822565b818152846020838601011115614b8757600080fd5b816020850160208301376000918101602001919091529392505050565b6bffffffffffffffffffffffff8116811461141757600080fd5b600082601f830112614bcf57600080fd5b81356020614bdf6148e883614871565b82815260c09283028501820192828201919087851115614bfe57600080fd5b8387015b85811015614c905781818a031215614c1a5760008081fd5b614c226147ff565b8135614c2d81614955565b815281860135614c3c8161498b565b81870152604082810135614c4f81614895565b90820152606082810135614c628161493b565b908201526080828101359082015260a080830135614c7f81614ba4565b908201528452928401928101614c02565b5090979650505050505050565b600080600080600080600080610100898b031215614cba57600080fd5b883567ffffffffffffffff80821115614cd257600080fd5b614cde8c838d016148c7565b995060208b0135915080821115614cf457600080fd5b614d008c838d016148c7565b9850614d0e60408c0161494a565b975060608b0135915080821115614d2457600080fd5b614d308c838d016149c2565b9650614d3e60808c01614afe565b955060a08b0135915080821115614d5457600080fd5b614d608c838d01614b16565b945060c08b0135915080821115614d7657600080fd5b614d828c838d016148c7565b935060e08b0135915080821115614d9857600080fd5b50614da58b828c01614bbe565b9150509295985092959890939650565b6000815180845260005b81811015614ddb57602081850181015186830182015201614dbf565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061225c6020830184614db5565b60008083601f840112614e3e57600080fd5b50813567ffffffffffffffff811115614e5657600080fd5b602083019150836020828501011115614e6e57600080fd5b9250929050565b60008060008060608587031215614e8b57600080fd5b8435614e9681614895565b935060208501359250604085013567ffffffffffffffff811115614eb957600080fd5b614ec587828801614e2c565b95989497509550505050565b60008083601f840112614ee357600080fd5b50813567ffffffffffffffff811115614efb57600080fd5b6020830191508360208260051b8501011115614e6e57600080fd5b60008060008060008060008060e0898b031215614f3257600080fd5b606089018a811115614f4357600080fd5b8998503567ffffffffffffffff80821115614f5d57600080fd5b614f698c838d01614e2c565b909950975060808b0135915080821115614f8257600080fd5b614f8e8c838d01614ed1565b909750955060a08b0135915080821115614fa757600080fd5b50614fb48b828c01614ed1565b999c989b50969995989497949560c00135949350505050565b60008060008060008060c08789031215614fe657600080fd5b863567ffffffffffffffff80821115614ffe57600080fd5b61500a8a838b016148c7565b9750602089013591508082111561502057600080fd5b61502c8a838b016148c7565b965061503a60408a0161494a565b9550606089013591508082111561505057600080fd5b61505c8a838b01614b16565b945061506a60808a01614afe565b935060a089013591508082111561508057600080fd5b5061508d89828a01614b16565b9150509295509295509295565b6000602082840312156150ac57600080fd5b813561225c81614895565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff81811683821602908116908181146135d0576135d06150b7565b60006020828403121561511457600080fd5b5051919050565b63ffffffff8181168382160190808211156135d0576135d06150b7565b600081518084526020808501945080840160005b8381101561517e57815173ffffffffffffffffffffffffffffffffffffffff168752958201959082019060010161514c565b509495945050505050565b602081526151a060208201835163ffffffff169052565b600060208301516151b9604084018263ffffffff169052565b50604083015163ffffffff8116606084015250606083015173ffffffffffffffffffffffffffffffffffffffff8116608084015250608083015180151560a08401525060a083015162ffffff811660c08401525060c083015163ffffffff811660e08401525060e08301516101006152388185018363ffffffff169052565b84015190506101206152618482018373ffffffffffffffffffffffffffffffffffffffff169052565b84015190506101406152788482018361ffff169052565b84015190506101606152a18482018373ffffffffffffffffffffffffffffffffffffffff169052565b840151610180848101919091528401516101a0808501919091528401516101c0808501919091528401516102006101e0808601829052919250906152e9610220860184615138565b95015173ffffffffffffffffffffffffffffffffffffffff169301929092525090919050565b8181038181111561224a5761224a6150b7565b600081615331576153316150b7565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036153b7576153b76150b7565b5060010190565b600061012063ffffffff808d1684528b6020850152808b166040850152508060608401526153ee8184018a615138565b905082810360808401526154028189615138565b905060ff871660a084015282810360c084015261541f8187614db5565b905067ffffffffffffffff851660e08401528281036101008401526154448185614db5565b9c9b505050505050505050505050565b60006020828403121561546657600080fd5b5035919050565b6bffffffffffffffffffffffff8181168382160190808211156135d0576135d06150b7565b8082018082111561224a5761224a6150b7565b60ff818116838216019081111561224a5761224a6150b7565b80516148c281614955565b80516148c281614895565b80516148c281614972565b80516148c28161498b565b80516148c2816149a7565b600082601f83011261550657600080fd5b815160206155166148e883614871565b82815260059290921b8401810191818101908684111561553557600080fd5b8286015b8481101561493057805161554c81614895565b8352918301918301615539565b600082601f83011261556a57600080fd5b8151602061557a6148e883614871565b82815260059290921b8401810191818101908684111561559957600080fd5b8286015b848110156149305780516155b081614895565b835291830191830161559d565b600082601f8301126155ce57600080fd5b815160206155de6148e883614871565b82815260c092830285018201928282019190878511156155fd57600080fd5b8387015b85811015614c905781818a0312156156195760008081fd5b6156216147ff565b815161562c81614955565b81528186015161563b8161498b565b8187015260408281015161564e81614895565b908201526060828101516156618161493b565b908201526080828101519082015260a08083015161567e81614ba4565b908201528452928401928101615601565b6000806000606084860312156156a457600080fd5b835167ffffffffffffffff808211156156bc57600080fd5b9085019061020082880312156156d157600080fd5b6156d96147d5565b6156e2836154be565b81526156f0602084016154be565b6020820152615701604084016154be565b6040820152615712606084016154c9565b6060820152615723608084016154d4565b608082015261573460a084016154df565b60a082015261574560c084016154be565b60c082015261575660e084016154be565b60e08201526101006157698185016154c9565b9082015261012061577b8482016154ea565b9082015261014061578d8482016154c9565b90820152610160838101519082015261018080840151908201526101a080840151908201526101c080840151838111156157c657600080fd5b6157d28a8287016154f5565b8284015250506101e06157e68185016154c9565b90820152602087015190955091508082111561580157600080fd5b61580d87838801615559565b9350604086015191508082111561582357600080fd5b50615830868287016155bd565b9150509250925092565b60006020828403121561584c57600080fd5b815161225c8161493b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b1660408501528160608501526158cd8285018b615138565b915083820360808501526158e1828a615138565b915060ff881660a085015283820360c08501526158fe8288614db5565b90861660e085015283810361010085015290506154448185614db5565b8183823760009101908152919050565b8281526080810160608360208401379392505050565b600082601f83011261595257600080fd5b813560206159626148e883614871565b82815260059290921b8401810191818101908684111561598157600080fd5b8286015b848110156149305780358352918301918301615985565b600082601f8301126159ad57600080fd5b813560206159bd6148e883614871565b82815260059290921b840181019181810190868411156159dc57600080fd5b8286015b8481101561493057803567ffffffffffffffff811115615a005760008081fd5b615a0e8986838b0101614b16565b8452509183019183016159e0565b600060208284031215615a2e57600080fd5b813567ffffffffffffffff80821115615a4657600080fd5b9083019060c08286031215615a5a57600080fd5b615a626147ff565b8235815260208301356020820152604083013582811115615a8257600080fd5b615a8e87828601615941565b604083015250606083013582811115615aa657600080fd5b615ab287828601615941565b606083015250608083013582811115615aca57600080fd5b615ad68782860161599c565b60808301525060a083013582811115615aee57600080fd5b615afa8782860161599c565b60a08301525095945050505050565b61ffff8181168382160190808211156135d0576135d06150b7565b808202811582820484141761224a5761224a6150b7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615b7957615b79615b3b565b500490565b6bffffffffffffffffffffffff85168152836020820152826040820152608060608201526000615bb16080830184614db5565b9695505050505050565b6bffffffffffffffffffffffff8281168282160390808211156135d0576135d06150b7565b60006bffffffffffffffffffffffff80841680615bff57615bff615b3b565b92169190910492915050565b6bffffffffffffffffffffffff818116838216028082169190828114615c3357615c336150b7565b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8281526040602082015260006136c96040830184614db5565b60008060408385031215615c9657600080fd5b8251615ca181614972565b6020939093015192949293505050565b805169ffffffffffffffffffff811681146148c257600080fd5b600080600080600060a08688031215615ce357600080fd5b615cec86615cb1565b9450602086015193506040860151925060608601519150615d0f60808701615cb1565b90509295509295909350565b6fffffffffffffffffffffffffffffffff8181168382160190808211156135d0576135d06150b7565b600060408284031215615d5657600080fd5b6040516040810181811067ffffffffffffffff82111715615d7957615d796147a6565b6040528251615d8781614955565b81526020928301519281019290925250919050565b600060a08284031215615dae57600080fd5b60405160a0810181811067ffffffffffffffff82111715615dd157615dd16147a6565b806040525082518152602083015160208201526040830151615df281614955565b60408201526060830151615e0581614955565b60608201526080928301519281019290925250919050565b600181815b80851115615e7657817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615e5c57615e5c6150b7565b80851615615e6957918102915b93841c9390800290615e22565b509250929050565b600082615e8d5750600161224a565b81615e9a5750600061224a565b8160018114615eb05760028114615eba57615ed6565b600191505061224a565b60ff841115615ecb57615ecb6150b7565b50506001821b61224a565b5060208310610133831016604e8410600b8410161715615ef9575081810a61224a565b615f038383615e1d565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615f3557615f356150b7565b029392505050565b600061225c8383615e7e56fea164736f6c6343000813000a", + Bin: "0x6101806040523480156200001257600080fd5b50604051620065f5380380620065f583398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e05161010051610120516101405161016051615ec1620007346000396000818160be01526101910152600050506000505060005050600050506000613a8201526000505060008181610d5401528181610e6201528181610f8d01528181610fd70152818161165901526130ab0152615ec16000f3fe6080604052600436106100bc5760003560e01c80638da5cb5b11610074578063b1dc65a41161004e578063b1dc65a4146102f6578063e3d0e71214610316578063f2fde38b14610336576100bc565b80638da5cb5b14610265578063a4c0ed3614610290578063afcb95d7146102b0576100bc565b8063349e8cca116100a5578063349e8cca1461018257806379ba5097146101d657806381ff7048146101eb576100bc565b80630870d3a114610103578063181f5a7714610123575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156100fc573d6000f35b3d6000fd5b005b34801561010f57600080fd5b5061010161011e366004614c08565b610356565b34801561012f57600080fd5b5061016c6040518060400160405280601881526020017f4175746f6d6174696f6e526567697374727920322e332e30000000000000000081525081565b6040516101799190614d84565b60405180910390f35b34801561018e57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610179565b3480156101e257600080fd5b50610101610c3a565b3480156101f757600080fd5b5061024260175460135463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610179565b34801561027157600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101b1565b34801561029c57600080fd5b506101016102ab366004614de0565b610d3c565b3480156102bc57600080fd5b50601354601454604080516000815260208101939093526c0100000000000000000000000090910463ffffffff1690820152606001610179565b34801561030257600080fd5b50610101610311366004614e81565b611058565b34801561032257600080fd5b50610101610331366004614f38565b611339565b34801561034257600080fd5b50610101610351366004615005565b611373565b61035e611387565b601f8851111561039a576040517f25d0209c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560ff166000036103d7576040517fe77dba5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b865188511415806103f657506103ee866003615051565b60ff16885111155b1561042d576040517f1d2d1c5800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051825114610468576040517fcf54c06a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610472828261140a565b61047c8888611a42565b604051806101200160405280601460000160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff168152602001600063ffffffff1681526020018660a0015162ffffff16815260200186610120015161ffff1681526020018760ff168152602001601460000160169054906101000a900460ff1615158152602001601460000160179054906101000a900460ff1615158152602001866080015115158152602001866101e0015173ffffffffffffffffffffffffffffffffffffffff16815250601460008201518160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550602082015181600001600c6101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160106101000a81548162ffffff021916908362ffffff16021790555060608201518160000160136101000a81548161ffff021916908361ffff16021790555060808201518160000160156101000a81548160ff021916908360ff16021790555060a08201518160000160166101000a81548160ff02191690831515021790555060c08201518160000160176101000a81548160ff02191690831515021790555060e08201518160000160186101000a81548160ff0219169083151502179055506101008201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050506000601660010160189054906101000a900463ffffffff1690506000866101e0015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa15801561072c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610750919061506d565b6017549091506000906107829074010000000000000000000000000000000000000000900463ffffffff166001615086565b9050604051806101600160405280896060015173ffffffffffffffffffffffffffffffffffffffff168152602001896000015163ffffffff168152602001896020015163ffffffff1681526020016016600001601c9054906101000a900463ffffffff1663ffffffff16815260200189610100015173ffffffffffffffffffffffffffffffffffffffff1681526020018263ffffffff1681526020018363ffffffff168152602001896040015163ffffffff16815260200189610140015173ffffffffffffffffffffffffffffffffffffffff1681526020018960c0015163ffffffff1681526020018960e0015163ffffffff16815250601660008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101208201518160020160146101000a81548163ffffffff021916908363ffffffff1602179055506101408201518160020160186101000a81548163ffffffff021916908363ffffffff160217905550905050876101600151601981905550876101800151601a81905550876101a00151601b81905550600088604051602001610ac591906150f4565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152919052601754909150610b2a904690309074010000000000000000000000000000000000000000900463ffffffff168f8f8f878f8f612101565b6013556000610b3960096121ab565b90505b8015610b7657610b63610b5b610b5360018461527a565b6009906121bb565b6009906121ce565b5080610b6e8161528d565b915050610b3c565b5060005b896101c0015151811015610bcd57610bba8a6101c001518281518110610ba257610ba26152c2565b602002602001015160096121f090919063ffffffff16565b5080610bc5816152f1565b915050610b7a565b507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0584601354601660010160149054906101000a900463ffffffff168f8f8f878f8f604051610c2499989796959493929190615329565b60405180910390a1505050505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610cc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610dab576040517fc8bad78d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208114610de5576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610df3828401846153bf565b6000818152600460205260409020549091506601000000000000900463ffffffff90811614610e4e576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020600201547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614610ed2576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260046020526040902060010154610f1190859070010000000000000000000000000000000090046bffffffffffffffffffffffff166153d8565b600082815260046020908152604080832060010180546bffffffffffffffffffffffff95909516700100000000000000000000000000000000027fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff9095169490941790935573ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168252602190522054610fc09085906153fd565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660009081526021602090815260409182902093909355516bffffffffffffffffffffffff871681529087169183917fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa734891506203910160405180910390a35050505050565b60005a60408051610120810182526014546bffffffffffffffffffffffff8116825263ffffffff6c01000000000000000000000000820416602083015262ffffff7001000000000000000000000000000000008204169282019290925261ffff730100000000000000000000000000000000000000830416606082015260ff75010000000000000000000000000000000000000000008304811660808301527601000000000000000000000000000000000000000000008304811615801560a08401527701000000000000000000000000000000000000000000000084048216151560c0840152780100000000000000000000000000000000000000000000000090930416151560e082015260155473ffffffffffffffffffffffffffffffffffffffff166101008201529192506111bc576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600b602052604090205460ff16611205576040517f1099ed7500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6013548a3514611241576040517fdfdcf8e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6080810151611251906001615410565b60ff16861415806112625750858414155b15611299576040517f0244f71a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112a98a8a8a8a8a8a8a8a612212565b60006112b58a8a61247b565b905060208b0135600881901c63ffffffff166112d2848487612534565b836020015163ffffffff168163ffffffff16111561132a57601480547fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff166c0100000000000000000000000063ffffffff8416021790555b50505050505050505050505050565b60008060008580602001905181019061135291906155fa565b9250925092506113688989898689898888610356565b505050505050505050565b61137b611387565b61138481613121565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611408576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610cb7565b565b60005b6024548110156114c857602260006024838154811061142e5761142e6152c2565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181019190915560020180547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169055806114c0816152f1565b91505061140d565b506114d56024600061465c565b60255460ff1660005b8351811015611a3c5760008482815181106114fb576114fb6152c2565b602002602001015190506000848381518110611519576115196152c2565b602002602001015190508173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561156e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159291906157a5565b60ff16816060015160ff161415806116205750806040015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161891906157a5565b60ff16600814155b15611657576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480156116c3575060018460018111156116c1576116c16157c2565b145b156116fa576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821615806117355750604081015173ffffffffffffffffffffffffffffffffffffffff16155b1561176c576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff828116600090815260226020526040902054670100000000000000900416156117d6576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6024805460018181019092557f7cd332d19b93bcabe3cce7ca0c18a052f57e5fd03b4758a09f30f5ddc4b22ec401805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216821790925560008181526022602090815260409182902086518154928801518489015160608a015160ff167b01000000000000000000000000000000000000000000000000000000027fffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffff9190981667010000000000000002167fffffffff000000000000000000000000000000000000000000ffffffffffffff62ffffff909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000090951663ffffffff9093169290921793909317929092169190911793909317835560808501519383019390935560a0840151600290920180546bffffffffffffffffffffffff9093167fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009093169290921790915590517fca93cbe727c73163ec538f71be6c0a64877d7f1f6dd35d5ca7cbaef3a3e34ba390611a1f908490600060c08201905063ffffffff835116825262ffffff602084015116602083015273ffffffffffffffffffffffffffffffffffffffff604084015116604083015260ff6060840151166060830152608083015160808301526bffffffffffffffffffffffff60a08401511660a083015292915050565b60405180910390a250508080611a34906152f1565b9150506114de565b50505050565b600e546014546bffffffffffffffffffffffff1660005b600e54811015611ab557611aa2600e8281548110611a7957611a796152c2565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff168385613216565b5080611aad816152f1565b915050611a59565b5060255460009060ff16815b600e54811015611c2657600e8181548110611ade57611ade6152c2565b6000918252602082200154600d805473ffffffffffffffffffffffffffffffffffffffff9092169550600c929184908110611b1b57611b1b6152c2565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168452838201949094526040928301822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690559286168152600b909252902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556001826001811115611bbd57611bbd6157c2565b148015611c02575073ffffffffffffffffffffffffffffffffffffffff83166000908152600b60205260409020546201000090046bffffffffffffffffffffffff1615155b15611c1457611c12600f846121f0565b505b80611c1e816152f1565b915050611ac1565b50611c33600d600061465c565b611c3f600e600061465c565b6040805160808101825260008082526020820181905291810182905260608101829052905b87518110156120cf57600c6000898381518110611c8357611c836152c2565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000205460ff1615611cee576040517f77cea0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16888281518110611d1857611d186152c2565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611d6d576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806001151581526020018260ff16815250600c60008a8481518110611d9e57611d9e6152c2565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528181019290925260400160002082518154939092015160ff16610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909316929092171790558651879082908110611e4657611e466152c2565b60200260200101519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611eb6576040517f58a70a0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152600b60209081526040918290208251608081018452905460ff80821615801584526101008304909116938301939093526bffffffffffffffffffffffff6201000082048116948301949094526e01000000000000000000000000000090049092166060830152909250611f71576040517f6a7281ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180835260ff80831660208086019182526014546bffffffffffffffffffffffff9081166060880190815273ffffffffffffffffffffffffffffffffffffffff8a166000908152600b909352604092839020885181549551948a0151925184166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff939094166201000002929092167fffffffffffff000000000000000000000000000000000000000000000000ffff94909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909516949094171791909116929092179190911790558360018111156120ab576120ab6157c2565b036120bd576120bb600f856121ce565b505b806120c7816152f1565b915050611c64565b5086516120e390600d9060208a019061467a565b5085516120f790600e90602089019061467a565b5050505050505050565b6000808a8a8a8a8a8a8a8a8a604051602001612125999897969594939291906157f1565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179b9a5050505050505050505050565b60006121b5825490565b92915050565b60006121c7838361341e565b9392505050565b60006121c78373ffffffffffffffffffffffffffffffffffffffff8416613448565b60006121c78373ffffffffffffffffffffffffffffffffffffffff8416613542565b60008787604051612224929190615886565b60405190819003812061223b918b90602001615896565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201208383019092526000808452908301819052909250906000805b88811015612412576001858783602081106122a7576122a76152c2565b6122b491901a601b615410565b8c8c858181106122c6576122c66152c2565b905060200201358b8b868181106122df576122df6152c2565b905060200201356040516000815260200160405260405161231c949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561233e573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff81166000908152600c602090815290849020838501909452925460ff80821615158085526101009092041693830193909352909550935090506123ec576040517f0f4c073700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826020015160080260ff166001901b84019350808061240a906152f1565b91505061228a565b50827e0101010101010101010101010101010101010101010101010101010101010184161461246d576040517fc103be2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050505050565b6124b46040518060c001604052806000815260200160008152602001606081526020016060815260200160608152602001606081525090565b60006124c283850185615987565b60408101515160608201515191925090811415806124e557508082608001515114155b806124f55750808260a001515114155b1561252c576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b509392505050565b600082604001515167ffffffffffffffff81111561255457612554614711565b60405190808252806020026020018201604052801561262057816020015b6040805161020081018252600060e08201818152610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e0830182905282526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816125725790505b50905060006040518060800160405280600061ffff16815260200160006bffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff16815260200160008152509050600085610100015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e2919061506d565b9050600086610100015173ffffffffffffffffffffffffffffffffffffffff166318b8f6136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612736573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275a919061506d565b905060005b866040015151811015612bea576004600088604001518381518110612786576127866152c2565b6020908102919091018101518252818101929092526040908101600020815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e08201526002909101549091169181019190915285518690839081106128a9576128a96152c2565b6020026020010151600001819052506128de876040015182815181106128d1576128d16152c2565b6020026020010151613591565b8582815181106128f0576128f06152c2565b602002602001015160600190600181111561290d5761290d6157c2565b90816001811115612920576129206157c2565b815250506129848760400151828151811061293d5761293d6152c2565b6020026020010151848960800151848151811061295c5761295c6152c2565b6020026020010151888581518110612976576129766152c2565b60200260200101518c61363c565b868381518110612996576129966152c2565b60200260200101516020018784815181106129b3576129b36152c2565b602002602001015160c00182815250821515151581525050508481815181106129de576129de6152c2565b60200260200101516020015115612a0e57600184600001818151612a029190615a74565b61ffff16905250612a13565b612bd8565b612a79858281518110612a2857612a286152c2565b6020026020010151600001516080015188606001518381518110612a4e57612a4e6152c2565b60200260200101518960a001518481518110612a6c57612a6c6152c2565b602002602001015161375b565b868381518110612a8b57612a8b6152c2565b6020026020010151604001878481518110612aa857612aa86152c2565b6020026020010151608001828152508215151515815250505087608001516001612ad29190615410565b612ae09060ff166040615a8f565b6103a48860a001518381518110612af957612af96152c2565b602002602001015151612b0c91906153fd565b612b1691906153fd565b858281518110612b2857612b286152c2565b602002602001015160a0018181525050848181518110612b4a57612b4a6152c2565b602002602001015160a0015184606001818151612b6791906153fd565b9052508451859082908110612b7e57612b7e6152c2565b60200260200101516080015186612b95919061527a565b9550612bd887604001518281518110612bb057612bb06152c2565b602002602001015184878481518110612bcb57612bcb6152c2565b6020026020010151613976565b80612be2816152f1565b91505061275f565b50825161ffff16600003612c015750505050505050565b61c800612c0f366010615a8f565b5a612c1a908861527a565b612c2491906153fd565b612c2e91906153fd565b83519095506123f090612c459061ffff1687615ad5565b612c4f91906153fd565b6040805160808101825260008082526020820181905291810182905260608101829052919650612c7e89613a7b565b905060005b886040015151811015612fba57868181518110612ca257612ca26152c2565b60200260200101516020015115612fa857801580612d3a575086612cc760018361527a565b81518110612cd757612cd76152c2565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff16878281518110612d1057612d106152c2565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff1614155b15612d6e57612d6b8a888381518110612d5557612d556152c2565b6020026020010151600001516101000151613b65565b92505b6000612e8c8b6040518061012001604052808b8681518110612d9257612d926152c2565b60200260200101516080015181526020018c81526020018a606001518c8781518110612dc057612dc06152c2565b602002602001015160a001518a612dd79190615a8f565b612de19190615ad5565b81526020018d6000015181526020018d6020015181526020018681526020018b8681518110612e1257612e126152c2565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff168152602001878152602001600115158152508c604001518581518110612e6157612e616152c2565b60200260200101518b8681518110612e7b57612e7b6152c2565b602002602001015160000151613ce1565b9050806060015187604001818151612ea491906153d8565b6bffffffffffffffffffffffff169052506040810151602088018051612ecb9083906153d8565b6bffffffffffffffffffffffff169052508751889083908110612ef057612ef06152c2565b60200260200101516040015115158a604001518381518110612f1457612f146152c2565b60200260200101517fad8cc9579b21dfe2c2f6ea35ba15b656e46b4f5b0cb424f52739b8ce5cac9c5b83606001518460400151612f5191906153d8565b8b8681518110612f6357612f636152c2565b6020026020010151608001518d8f608001518881518110612f8657612f866152c2565b6020026020010151604051612f9e9493929190615ae9565b60405180910390a3505b80612fb2816152f1565b915050612c83565b505050602083810151336000908152600b90925260409091208054600290612ff79084906201000090046bffffffffffffffffffffffff166153d8565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508260400151601460000160008282829054906101000a90046bffffffffffffffffffffffff1661305591906153d8565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508260400151836020015161309791906153d8565b6bffffffffffffffffffffffff16602160007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461311391906153fd565b909155505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036131a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610cb7565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e01000000000000000000000000000090049091166060820152906134125760008160600151856132ae9190615b26565b905060006132bc8583615b4b565b905080836040018181516132d091906153d8565b6bffffffffffffffffffffffff169052506132eb8582615b76565b836060018181516132fc91906153d8565b6bffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff89166000908152600b602090815260409182902087518154928901519389015160608a015186166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff919096166201000002167fffffffffffff000000000000000000000000000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909416939093171792909216179190911790555050505b60400151949350505050565b6000826000018281548110613435576134356152c2565b9060005260206000200154905092915050565b6000818152600183016020526040812054801561353157600061346c60018361527a565b85549091506000906134809060019061527a565b90508181146134e55760008660000182815481106134a0576134a06152c2565b90600052602060002001549050808760000184815481106134c3576134c36152c2565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806134f6576134f6615ba6565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506121b5565b60009150506121b5565b5092915050565b6000818152600183016020526040812054613589575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556121b5565b5060006121b5565b6000818160045b600f81101561361e577fff0000000000000000000000000000000000000000000000000000000000000082168382602081106135d6576135d66152c2565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461360c57506000949350505050565b80613616816152f1565b915050613598565b5081600f1a6001811115613634576136346157c2565b949350505050565b600080808085606001516001811115613657576136576157c2565b0361367d576136698888888888613fdd565b61367857600092509050613751565b6136f5565b600185606001516001811115613695576136956157c2565b036136c35760006136a889898988614167565b92509050806136bd5750600092509050613751565b506136f5565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516060015163ffffffff16871061374a57877fc3237c8807c467c1b39b8d0395eff077313e691bf0a7388106792564ebfd5636876040516137379190614d84565b60405180910390a2600092509050613751565b6001925090505b9550959350505050565b601454600090819077010000000000000000000000000000000000000000000000900460ff16156137b8576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b000000000000000000000000000000000000000000000000000000009061382d908590602401614d84565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d16906139009087908790600401615bd5565b60408051808303816000875af115801561391e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139429190615bee565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b60008160600151600181111561398e5761398e6157c2565b036139f257600083815260046020526040902060010180547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000063ffffffff851602179055505050565b600181606001516001811115613a0a57613a0a6157c2565b03613a765760c08101805160009081526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055915191517fa4a4e334c0e330143f9437484fe516c13bc560b86b5b0daf58e7084aaac228f29190a25b505050565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613aeb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b0f9190615c36565b50935050925050600082131580613b2557508042105b80613b5557506000846040015162ffffff16118015613b555750613b49814261527a565b846040015162ffffff16105b1561353b575050601b5492915050565b60408051608081018252600080825260208083018281528385018381526060850184905273ffffffffffffffffffffffffffffffffffffffff878116855260229093528584208054640100000000810462ffffff1690925263ffffffff82169092527b01000000000000000000000000000000000000000000000000000000810460ff16855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495919484936701000000000000009092049091169163feaf968c9160048083019260a09291908290030181865afa158015613c52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c769190615c36565b50935050925050600082131580613c8c57508042105b80613cbc57506000866040015162ffffff16118015613cbc5750613cb0814261527a565b866040015162ffffff16105b15613cd05760018301546060850152613cd8565b606084018290525b50505092915050565b604080516080810182526000808252602080830182905292820181905260608201529082015115613d5a5760008381526023602090815260409182902082518084018452905463ffffffff811680835262ffffff640100000000909204821692840192835260e089018051909401529051915191169101525b6000613d668686614374565b60c0840151602082015182519293509091600091613d83916153d8565b905082600001516bffffffffffffffffffffffff16826bffffffffffffffffffffffff161015613e0857819050613de987608001518860e0015160600151846bffffffffffffffffffffffff16613dda9190615a8f565b613de49190615ad5565b6145ba565b6bffffffffffffffffffffffff16604084015260006060840152613e94565b806bffffffffffffffffffffffff16826bffffffffffffffffffffffff161015613e9457819050613e8083604001516bffffffffffffffffffffffff1688608001518960e0015160600151856bffffffffffffffffffffffff16613e6c9190615a8f565b613e769190615ad5565b613de4919061527a565b6bffffffffffffffffffffffff1660608401525b60008681526004602052604090206001018054829190601090613eda90849070010000000000000000000000000000000090046bffffffffffffffffffffffff16615b26565b82546101009290920a6bffffffffffffffffffffffff81810219909316918316021790915560008881526004602052604081206001018054928516935091613f359084906fffffffffffffffffffffffffffffffff16615c86565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550806bffffffffffffffffffffffff16602160008960c0015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254613fcc919061527a565b909155509298975050505050505050565b60008084806020019051810190613ff49190615caf565b845160e00151815191925063ffffffff9081169116101561405157867f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e88660405161403f9190614d84565b60405180910390a2600091505061415e565b8260e00151801561411157506020810151158015906141115750602081015161010084015182516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa1580156140ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061410e919061506d565b14155b806141235750805163ffffffff168611155b1561415857867f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc3018660405161403f9190614d84565b60019150505b95945050505050565b6000806000848060200190518101906141809190615d07565b90506000878260000151836020015184604001516040516020016141e294939291909384526020840192909252604083015260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016606082015260640190565b6040516020818303038152906040528051906020012090508460e0015180156142bd57506080820151158015906142bd5750608082015161010086015160608401516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa158015614296573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142ba919061506d565b14155b806142d2575086826060015163ffffffff1610155b1561431c57877f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc301876040516143079190614d84565b60405180910390a260009350915061436b9050565b60008181526008602052604090205460ff161561436357877f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e8876040516143079190614d84565b600193509150505b94509492505050565b60408051608081018252600080825260208201819052918101829052606081019190915260008260e001516000015160ff1690506000846060015161ffff1684606001516143c29190615a8f565b905083610100015180156143d55750803a105b156143dd57503a5b6000601283116143ee576001614404565b6143f960128461527a565b61440490600a615ea8565b905060006012841061441757600161442d565b61442284601261527a565b61442d90600a615ea8565b905060008660a0015187604001518860200151896000015161444f91906153fd565b6144599087615a8f565b61446391906153fd565b61446d9190615a8f565b9050614490828860e00151606001516144869190615a8f565b613dda8584615a8f565b6bffffffffffffffffffffffff16865260808701516144b390613de49083615ad5565b6bffffffffffffffffffffffff1660408088019190915260e088015101516000906144ec9062ffffff16683635c9adc5dea00000615a8f565b9050600081633b9aca008a60a001518b60e001516020015163ffffffff168c604001518d600001518b61451f9190615a8f565b61452991906153fd565b6145339190615a8f565b61453d9190615a8f565b6145479190615ad5565b61455191906153fd565b9050614574848a60e001516060015161456a9190615a8f565b613dda8784615a8f565b6bffffffffffffffffffffffff166020890152608089015161459a90613de49083615ad5565b6bffffffffffffffffffffffff1660608901525050505050505092915050565b60006bffffffffffffffffffffffff821115614658576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610cb7565b5090565b508054600082559060005260206000209081019061138491906146fc565b8280548282559060005260206000209081019282156146f4579160200282015b828111156146f457825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061469a565b506146589291505b5b8082111561465857600081556001016146fd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610200810167ffffffffffffffff8111828210171561476457614764614711565b60405290565b60405160c0810167ffffffffffffffff8111828210171561476457614764614711565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156147d4576147d4614711565b604052919050565b600067ffffffffffffffff8211156147f6576147f6614711565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff8116811461138457600080fd5b803561482d81614800565b919050565b600082601f83011261484357600080fd5b81356020614858614853836147dc565b61478d565b82815260059290921b8401810191818101908684111561487757600080fd5b8286015b8481101561489b57803561488e81614800565b835291830191830161487b565b509695505050505050565b60ff8116811461138457600080fd5b803561482d816148a6565b63ffffffff8116811461138457600080fd5b803561482d816148c0565b801515811461138457600080fd5b803561482d816148dd565b62ffffff8116811461138457600080fd5b803561482d816148f6565b61ffff8116811461138457600080fd5b803561482d81614912565b6000610200828403121561494057600080fd5b614948614740565b9050614953826148d2565b8152614961602083016148d2565b6020820152614972604083016148d2565b604082015261498360608301614822565b6060820152614994608083016148eb565b60808201526149a560a08301614907565b60a08201526149b660c083016148d2565b60c08201526149c760e083016148d2565b60e08201526101006149da818401614822565b908201526101206149ec838201614922565b908201526101406149fe838201614822565b90820152610160828101359082015261018080830135908201526101a080830135908201526101c08083013567ffffffffffffffff811115614a3f57600080fd5b614a4b85828601614832565b8284015250506101e0614a5f818401614822565b9082015292915050565b803567ffffffffffffffff8116811461482d57600080fd5b600082601f830112614a9257600080fd5b813567ffffffffffffffff811115614aac57614aac614711565b614add60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161478d565b818152846020838601011115614af257600080fd5b816020850160208301376000918101602001919091529392505050565b6bffffffffffffffffffffffff8116811461138457600080fd5b600082601f830112614b3a57600080fd5b81356020614b4a614853836147dc565b82815260c09283028501820192828201919087851115614b6957600080fd5b8387015b85811015614bfb5781818a031215614b855760008081fd5b614b8d61476a565b8135614b98816148c0565b815281860135614ba7816148f6565b81870152604082810135614bba81614800565b90820152606082810135614bcd816148a6565b908201526080828101359082015260a080830135614bea81614b0f565b908201528452928401928101614b6d565b5090979650505050505050565b600080600080600080600080610100898b031215614c2557600080fd5b883567ffffffffffffffff80821115614c3d57600080fd5b614c498c838d01614832565b995060208b0135915080821115614c5f57600080fd5b614c6b8c838d01614832565b9850614c7960408c016148b5565b975060608b0135915080821115614c8f57600080fd5b614c9b8c838d0161492d565b9650614ca960808c01614a69565b955060a08b0135915080821115614cbf57600080fd5b614ccb8c838d01614a81565b945060c08b0135915080821115614ce157600080fd5b614ced8c838d01614832565b935060e08b0135915080821115614d0357600080fd5b50614d108b828c01614b29565b9150509295985092959890939650565b6000815180845260005b81811015614d4657602081850181015186830182015201614d2a565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006121c76020830184614d20565b60008083601f840112614da957600080fd5b50813567ffffffffffffffff811115614dc157600080fd5b602083019150836020828501011115614dd957600080fd5b9250929050565b60008060008060608587031215614df657600080fd5b8435614e0181614800565b935060208501359250604085013567ffffffffffffffff811115614e2457600080fd5b614e3087828801614d97565b95989497509550505050565b60008083601f840112614e4e57600080fd5b50813567ffffffffffffffff811115614e6657600080fd5b6020830191508360208260051b8501011115614dd957600080fd5b60008060008060008060008060e0898b031215614e9d57600080fd5b606089018a811115614eae57600080fd5b8998503567ffffffffffffffff80821115614ec857600080fd5b614ed48c838d01614d97565b909950975060808b0135915080821115614eed57600080fd5b614ef98c838d01614e3c565b909750955060a08b0135915080821115614f1257600080fd5b50614f1f8b828c01614e3c565b999c989b50969995989497949560c00135949350505050565b60008060008060008060c08789031215614f5157600080fd5b863567ffffffffffffffff80821115614f6957600080fd5b614f758a838b01614832565b97506020890135915080821115614f8b57600080fd5b614f978a838b01614832565b9650614fa560408a016148b5565b95506060890135915080821115614fbb57600080fd5b614fc78a838b01614a81565b9450614fd560808a01614a69565b935060a0890135915080821115614feb57600080fd5b50614ff889828a01614a81565b9150509295509295509295565b60006020828403121561501757600080fd5b81356121c781614800565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff818116838216029081169081811461353b5761353b615022565b60006020828403121561507f57600080fd5b5051919050565b63ffffffff81811683821601908082111561353b5761353b615022565b600081518084526020808501945080840160005b838110156150e957815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016150b7565b509495945050505050565b6020815261510b60208201835163ffffffff169052565b60006020830151615124604084018263ffffffff169052565b50604083015163ffffffff8116606084015250606083015173ffffffffffffffffffffffffffffffffffffffff8116608084015250608083015180151560a08401525060a083015162ffffff811660c08401525060c083015163ffffffff811660e08401525060e08301516101006151a38185018363ffffffff169052565b84015190506101206151cc8482018373ffffffffffffffffffffffffffffffffffffffff169052565b84015190506101406151e38482018361ffff169052565b840151905061016061520c8482018373ffffffffffffffffffffffffffffffffffffffff169052565b840151610180848101919091528401516101a0808501919091528401516101c0808501919091528401516102006101e0808601829052919250906152546102208601846150a3565b95015173ffffffffffffffffffffffffffffffffffffffff169301929092525090919050565b818103818111156121b5576121b5615022565b60008161529c5761529c615022565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361532257615322615022565b5060010190565b600061012063ffffffff808d1684528b6020850152808b166040850152508060608401526153598184018a6150a3565b9050828103608084015261536d81896150a3565b905060ff871660a084015282810360c084015261538a8187614d20565b905067ffffffffffffffff851660e08401528281036101008401526153af8185614d20565b9c9b505050505050505050505050565b6000602082840312156153d157600080fd5b5035919050565b6bffffffffffffffffffffffff81811683821601908082111561353b5761353b615022565b808201808211156121b5576121b5615022565b60ff81811683821601908111156121b5576121b5615022565b805161482d816148c0565b805161482d81614800565b805161482d816148dd565b805161482d816148f6565b805161482d81614912565b600082601f83011261547157600080fd5b81516020615481614853836147dc565b82815260059290921b840181019181810190868411156154a057600080fd5b8286015b8481101561489b5780516154b781614800565b83529183019183016154a4565b600082601f8301126154d557600080fd5b815160206154e5614853836147dc565b82815260059290921b8401810191818101908684111561550457600080fd5b8286015b8481101561489b57805161551b81614800565b8352918301918301615508565b600082601f83011261553957600080fd5b81516020615549614853836147dc565b82815260c0928302850182019282820191908785111561556857600080fd5b8387015b85811015614bfb5781818a0312156155845760008081fd5b61558c61476a565b8151615597816148c0565b8152818601516155a6816148f6565b818701526040828101516155b981614800565b908201526060828101516155cc816148a6565b908201526080828101519082015260a0808301516155e981614b0f565b90820152845292840192810161556c565b60008060006060848603121561560f57600080fd5b835167ffffffffffffffff8082111561562757600080fd5b90850190610200828803121561563c57600080fd5b615644614740565b61564d83615429565b815261565b60208401615429565b602082015261566c60408401615429565b604082015261567d60608401615434565b606082015261568e6080840161543f565b608082015261569f60a0840161544a565b60a08201526156b060c08401615429565b60c08201526156c160e08401615429565b60e08201526101006156d4818501615434565b908201526101206156e6848201615455565b908201526101406156f8848201615434565b90820152610160838101519082015261018080840151908201526101a080840151908201526101c0808401518381111561573157600080fd5b61573d8a828701615460565b8284015250506101e0615751818501615434565b90820152602087015190955091508082111561576c57600080fd5b615778878388016154c4565b9350604086015191508082111561578e57600080fd5b5061579b86828701615528565b9150509250925092565b6000602082840312156157b757600080fd5b81516121c7816148a6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b1660408501528160608501526158388285018b6150a3565b9150838203608085015261584c828a6150a3565b915060ff881660a085015283820360c08501526158698288614d20565b90861660e085015283810361010085015290506153af8185614d20565b8183823760009101908152919050565b8281526080810160608360208401379392505050565b600082601f8301126158bd57600080fd5b813560206158cd614853836147dc565b82815260059290921b840181019181810190868411156158ec57600080fd5b8286015b8481101561489b57803583529183019183016158f0565b600082601f83011261591857600080fd5b81356020615928614853836147dc565b82815260059290921b8401810191818101908684111561594757600080fd5b8286015b8481101561489b57803567ffffffffffffffff81111561596b5760008081fd5b6159798986838b0101614a81565b84525091830191830161594b565b60006020828403121561599957600080fd5b813567ffffffffffffffff808211156159b157600080fd5b9083019060c082860312156159c557600080fd5b6159cd61476a565b82358152602083013560208201526040830135828111156159ed57600080fd5b6159f9878286016158ac565b604083015250606083013582811115615a1157600080fd5b615a1d878286016158ac565b606083015250608083013582811115615a3557600080fd5b615a4187828601615907565b60808301525060a083013582811115615a5957600080fd5b615a6587828601615907565b60a08301525095945050505050565b61ffff81811683821601908082111561353b5761353b615022565b80820281158282048414176121b5576121b5615022565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615ae457615ae4615aa6565b500490565b6bffffffffffffffffffffffff85168152836020820152826040820152608060608201526000615b1c6080830184614d20565b9695505050505050565b6bffffffffffffffffffffffff82811682821603908082111561353b5761353b615022565b60006bffffffffffffffffffffffff80841680615b6a57615b6a615aa6565b92169190910492915050565b6bffffffffffffffffffffffff818116838216028082169190828114615b9e57615b9e615022565b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8281526040602082015260006136346040830184614d20565b60008060408385031215615c0157600080fd5b8251615c0c816148dd565b6020939093015192949293505050565b805169ffffffffffffffffffff8116811461482d57600080fd5b600080600080600060a08688031215615c4e57600080fd5b615c5786615c1c565b9450602086015193506040860151925060608601519150615c7a60808701615c1c565b90509295509295909350565b6fffffffffffffffffffffffffffffffff81811683821601908082111561353b5761353b615022565b600060408284031215615cc157600080fd5b6040516040810181811067ffffffffffffffff82111715615ce457615ce4614711565b6040528251615cf2816148c0565b81526020928301519281019290925250919050565b600060a08284031215615d1957600080fd5b60405160a0810181811067ffffffffffffffff82111715615d3c57615d3c614711565b806040525082518152602083015160208201526040830151615d5d816148c0565b60408201526060830151615d70816148c0565b60608201526080928301519281019290925250919050565b600181815b80851115615de157817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615dc757615dc7615022565b80851615615dd457918102915b93841c9390800290615d8d565b509250929050565b600082615df8575060016121b5565b81615e05575060006121b5565b8160018114615e1b5760028114615e2557615e41565b60019150506121b5565b60ff841115615e3657615e36615022565b50506001821b6121b5565b5060208310610133831016604e8410600b8410161715615e64575081810a6121b5565b615e6e8383615d88565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615ea057615ea0615022565b029392505050565b60006121c78383615de956fea164736f6c6343000813000a", } var AutomationRegistryABI = AutomationRegistryMetaData.ABI diff --git a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt index a8dae2092cb..d5a931321ab 100644 --- a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -8,13 +8,13 @@ automation_compatible_utils: ../../contracts/solc/v0.8.19/AutomationCompatibleUt automation_consumer_benchmark: ../../contracts/solc/v0.8.16/AutomationConsumerBenchmark/AutomationConsumerBenchmark.abi ../../contracts/solc/v0.8.16/AutomationConsumerBenchmark/AutomationConsumerBenchmark.bin f52c76f1aaed4be541d82d97189d70f5aa027fc9838037dd7a7d21910c8c488e automation_forwarder_logic: ../../contracts/solc/v0.8.16/AutomationForwarderLogic/AutomationForwarderLogic.abi ../../contracts/solc/v0.8.16/AutomationForwarderLogic/AutomationForwarderLogic.bin 15ae0c367297955fdab4b552dbb10e1f2be80a8fde0efec4a4d398693e9d72b5 automation_registrar_wrapper2_1: ../../contracts/solc/v0.8.16/AutomationRegistrar2_1/AutomationRegistrar2_1.abi ../../contracts/solc/v0.8.16/AutomationRegistrar2_1/AutomationRegistrar2_1.bin eb06d853aab39d3196c593b03e555851cbe8386e0fe54a74c2479f62d14b3c42 -automation_registrar_wrapper2_3: ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.bin 4d8c1fae4c8bf59ad996a1ac00f2131158ac1d96c3039c2e7deaa502f0317719 +automation_registrar_wrapper2_3: ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.bin 05dfc1601a6e8a43d98c982b5cb1ad1060b49948dc0c8ccd829ca2c9f6d9430e automation_registry_logic_a_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_2/AutomationRegistryLogicA2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_2/AutomationRegistryLogicA2_2.bin 2f267fb8467a15c587ce4586ac56069f7229344ad3936430d7c7624c0528a171 -automation_registry_logic_a_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.bin 1163ecd34c575cb17ffbc2f88fa175816f36982e91992d940ed435d306b3418c +automation_registry_logic_a_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.bin e8ae5a25765092049f79eb8344db8e572bacb43c6c6e284b3d00f82667c248f7 automation_registry_logic_b_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_2/AutomationRegistryLogicB2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_2/AutomationRegistryLogicB2_2.bin a6d33dfbbfb0ff253eb59a51f4f6d6d4c22ea5ec95aae52d25d49a312b37a22f automation_registry_logic_b_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.bin 2d0f45d2087f6f3c8bfa0a16b26a1c8c1d5c64b89859478c609201535c96eeed automation_registry_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistry2_2/AutomationRegistry2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_2/AutomationRegistry2_2.bin de60f69878e9b32a291a001c91fc8636544c2cfbd9b507c8c1a4873b602bfb62 -automation_registry_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.bin 68acf720890c89512a43c3468712f5da6c1c9613bc7c462b51599293f0cce9f4 +automation_registry_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.bin fa9159b9dd36e37209d9805d0fde82f1cba7d0e2674ecc5a7595d48eb40203c4 automation_utils_2_1: ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.abi ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.bin 815b17b63f15d26a0274b962eefad98cdee4ec897ead58688bbb8e2470e585f5 automation_utils_2_2: ../../contracts/solc/v0.8.19/AutomationUtils2_2/AutomationUtils2_2.abi ../../contracts/solc/v0.8.19/AutomationUtils2_2/AutomationUtils2_2.bin 8743f6231aaefa3f2a0b2d484258070d506e2d0860690e66890dccc3949edb2e automation_utils_2_3: ../../contracts/solc/v0.8.19/AutomationUtils2_3/AutomationUtils2_3.abi ../../contracts/solc/v0.8.19/AutomationUtils2_3/AutomationUtils2_3.bin 11e2b481dc9a4d936e3443345d45d2cc571164459d214917b42a8054b295393b From 9c948c7d30b748ce0d881e88b492237db03ebe9d Mon Sep 17 00:00:00 2001 From: Erik Burton Date: Thu, 25 Apr 2024 12:42:50 -0700 Subject: [PATCH 20/34] fix: disable gh releases for contracts (#12980) --- .github/workflows/solidity.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/solidity.yml b/.github/workflows/solidity.yml index 5940313fc65..b2dc3d4153c 100644 --- a/.github/workflows/solidity.yml +++ b/.github/workflows/solidity.yml @@ -258,10 +258,7 @@ jobs: uses: smartcontractkit/.github/actions/ci-publish-npm@4b0ab756abcb1760cb82e1e87b94ff431905bffc # ci-publish-npm@0.4.0 with: npm-token: ${{ secrets.NPM_TOKEN }} - github-token: ${{ secrets.GITHUB_TOKEN }} - github-release-tag-name: ${{ github.ref_name }} - github-release-changelog-path: "contracts/CHANGELOG.md" - create-github-release: true + create-github-release: false publish-command: "pnpm publish-prod --no-git-checks" package-json-directory: contracts From aab15199469180a6e193931d2a70f0c52442ebc2 Mon Sep 17 00:00:00 2001 From: Cedric Date: Thu, 25 Apr 2024 21:21:06 +0100 Subject: [PATCH 21/34] [KS-137] Add support for execution strategies (#12841) * [KS-137] Add support for execution strategies * [KS-137] Add support for execution strategies --- core/capabilities/remote/target.go | 9 +- core/capabilities/remote/target_test.go | 4 +- core/capabilities/remote/trigger_publisher.go | 6 +- .../remote/trigger_publisher_test.go | 6 +- .../capabilities/remote/trigger_subscriber.go | 8 +- .../remote/trigger_subscriber_test.go | 4 +- core/capabilities/syncer.go | 10 +- core/services/chainlink/application.go | 28 ++- core/services/workflows/delegate.go | 52 ++++- core/services/workflows/engine.go | 187 ++++++++++++------ core/services/workflows/engine_test.go | 10 + core/services/workflows/execution_strategy.go | 171 ++++++++++++++++ .../workflows/execution_strategy_test.go | 170 ++++++++++++++++ core/services/workflows/models.go | 10 +- core/services/workflows/models_yaml.go | 18 +- .../marshalling/workflow_2_spec.json | 2 +- 16 files changed, 601 insertions(+), 94 deletions(-) create mode 100644 core/services/workflows/execution_strategy.go create mode 100644 core/services/workflows/execution_strategy_test.go diff --git a/core/capabilities/remote/target.go b/core/capabilities/remote/target.go index 92b0724512a..655f4f84abb 100644 --- a/core/capabilities/remote/target.go +++ b/core/capabilities/remote/target.go @@ -4,6 +4,7 @@ import ( "context" "errors" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -12,7 +13,7 @@ import ( // remoteTargetCaller/Receiver are shims translating between capability API calls and network messages type remoteTargetCaller struct { capInfo commoncap.CapabilityInfo - donInfo *types.DON + donInfo *capabilities.DON dispatcher types.Dispatcher lggr logger.Logger } @@ -22,14 +23,14 @@ var _ types.Receiver = &remoteTargetCaller{} type remoteTargetReceiver struct { capInfo commoncap.CapabilityInfo - donInfo *types.DON + donInfo *capabilities.DON dispatcher types.Dispatcher lggr logger.Logger } var _ types.Receiver = &remoteTargetReceiver{} -func NewRemoteTargetCaller(capInfo commoncap.CapabilityInfo, donInfo *types.DON, dispatcher types.Dispatcher, lggr logger.Logger) *remoteTargetCaller { +func NewRemoteTargetCaller(capInfo commoncap.CapabilityInfo, donInfo *capabilities.DON, dispatcher types.Dispatcher, lggr logger.Logger) *remoteTargetCaller { return &remoteTargetCaller{ capInfo: capInfo, donInfo: donInfo, @@ -72,7 +73,7 @@ func (c *remoteTargetCaller) Receive(msg *types.MessageBody) { c.lggr.Debugw("not implemented - received message", "capabilityId", c.capInfo.ID, "payload", msg.Payload) } -func NewRemoteTargetReceiver(capInfo commoncap.CapabilityInfo, donInfo *types.DON, dispatcher types.Dispatcher, lggr logger.Logger) *remoteTargetReceiver { +func NewRemoteTargetReceiver(capInfo commoncap.CapabilityInfo, donInfo *capabilities.DON, dispatcher types.Dispatcher, lggr logger.Logger) *remoteTargetReceiver { return &remoteTargetReceiver{ capInfo: capInfo, donInfo: donInfo, diff --git a/core/capabilities/remote/target_test.go b/core/capabilities/remote/target_test.go index a9e72d778df..0f9bad51f67 100644 --- a/core/capabilities/remote/target_test.go +++ b/core/capabilities/remote/target_test.go @@ -6,9 +6,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" remoteMocks "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -18,7 +18,7 @@ import ( func TestTarget_Placeholder(t *testing.T) { lggr := logger.TestLogger(t) ctx := testutils.Context(t) - donInfo := &types.DON{ + donInfo := &capabilities.DON{ Members: []p2ptypes.PeerID{{}}, } dispatcher := remoteMocks.NewDispatcher(t) diff --git a/core/capabilities/remote/trigger_publisher.go b/core/capabilities/remote/trigger_publisher.go index d06254657c7..12d539a2dc0 100644 --- a/core/capabilities/remote/trigger_publisher.go +++ b/core/capabilities/remote/trigger_publisher.go @@ -24,8 +24,8 @@ type triggerPublisher struct { config types.RemoteTriggerConfig underlying commoncap.TriggerCapability capInfo commoncap.CapabilityInfo - capDonInfo types.DON - workflowDONs map[string]types.DON + capDonInfo commoncap.DON + workflowDONs map[string]commoncap.DON dispatcher types.Dispatcher messageCache *messageCache[registrationKey, p2ptypes.PeerID] registrations map[registrationKey]*pubRegState @@ -48,7 +48,7 @@ type pubRegState struct { var _ types.Receiver = &triggerPublisher{} var _ services.Service = &triggerPublisher{} -func NewTriggerPublisher(config types.RemoteTriggerConfig, underlying commoncap.TriggerCapability, capInfo commoncap.CapabilityInfo, capDonInfo types.DON, workflowDONs map[string]types.DON, dispatcher types.Dispatcher, lggr logger.Logger) *triggerPublisher { +func NewTriggerPublisher(config types.RemoteTriggerConfig, underlying commoncap.TriggerCapability, capInfo commoncap.CapabilityInfo, capDonInfo commoncap.DON, workflowDONs map[string]commoncap.DON, dispatcher types.Dispatcher, lggr logger.Logger) *triggerPublisher { config.ApplyDefaults() return &triggerPublisher{ config: config, diff --git a/core/capabilities/remote/trigger_publisher_test.go b/core/capabilities/remote/trigger_publisher_test.go index dd107e12e61..71a5174c07f 100644 --- a/core/capabilities/remote/trigger_publisher_test.go +++ b/core/capabilities/remote/trigger_publisher_test.go @@ -29,12 +29,12 @@ func TestTriggerPublisher_Register(t *testing.T) { require.NoError(t, p1.UnmarshalText([]byte(peerID1))) p2 := p2ptypes.PeerID{} require.NoError(t, p2.UnmarshalText([]byte(peerID2))) - capDonInfo := remotetypes.DON{ + capDonInfo := commoncap.DON{ ID: "capability-don", Members: []p2ptypes.PeerID{p1}, F: 0, } - workflowDonInfo := remotetypes.DON{ + workflowDonInfo := commoncap.DON{ ID: "workflow-don", Members: []p2ptypes.PeerID{p2}, F: 0, @@ -47,7 +47,7 @@ func TestTriggerPublisher_Register(t *testing.T) { MinResponsesToAggregate: 1, MessageExpiryMs: 100_000, } - workflowDONs := map[string]remotetypes.DON{ + workflowDONs := map[string]commoncap.DON{ workflowDonInfo.ID: workflowDonInfo, } underlying := &testTrigger{ diff --git a/core/capabilities/remote/trigger_subscriber.go b/core/capabilities/remote/trigger_subscriber.go index a7cb58c008b..e9704bf1865 100644 --- a/core/capabilities/remote/trigger_subscriber.go +++ b/core/capabilities/remote/trigger_subscriber.go @@ -6,6 +6,7 @@ import ( sync "sync" "time" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/services" @@ -24,9 +25,9 @@ import ( type triggerSubscriber struct { config types.RemoteTriggerConfig capInfo commoncap.CapabilityInfo - capDonInfo types.DON + capDonInfo capabilities.DON capDonMembers map[p2ptypes.PeerID]struct{} - localDonInfo types.DON + localDonInfo capabilities.DON dispatcher types.Dispatcher aggregator types.Aggregator messageCache *messageCache[triggerEventKey, p2ptypes.PeerID] @@ -54,8 +55,7 @@ var _ services.Service = &triggerSubscriber{} // TODO makes this configurable with a default const defaultSendChannelBufferSize = 1000 -func NewTriggerSubscriber(config types.RemoteTriggerConfig, capInfo commoncap.CapabilityInfo, capDonInfo types.DON, localDonInfo types.DON, - dispatcher types.Dispatcher, aggregator types.Aggregator, lggr logger.Logger) *triggerSubscriber { +func NewTriggerSubscriber(config types.RemoteTriggerConfig, capInfo commoncap.CapabilityInfo, capDonInfo capabilities.DON, localDonInfo capabilities.DON, dispatcher types.Dispatcher, aggregator types.Aggregator, lggr logger.Logger) *triggerSubscriber { if aggregator == nil { lggr.Warnw("no aggregator provided, using default MODE aggregator", "capabilityId", capInfo.ID) aggregator = NewDefaultModeAggregator(uint32(capDonInfo.F + 1)) diff --git a/core/capabilities/remote/trigger_subscriber_test.go b/core/capabilities/remote/trigger_subscriber_test.go index df04306e2b0..4d251d49dc8 100644 --- a/core/capabilities/remote/trigger_subscriber_test.go +++ b/core/capabilities/remote/trigger_subscriber_test.go @@ -38,12 +38,12 @@ func TestTriggerSubscriber_RegisterAndReceive(t *testing.T) { require.NoError(t, p1.UnmarshalText([]byte(peerID1))) p2 := p2ptypes.PeerID{} require.NoError(t, p2.UnmarshalText([]byte(peerID2))) - capDonInfo := remotetypes.DON{ + capDonInfo := commoncap.DON{ ID: "capability-don", Members: []p2ptypes.PeerID{p1}, F: 0, } - workflowDonInfo := remotetypes.DON{ + workflowDonInfo := commoncap.DON{ ID: "workflow-don", Members: []p2ptypes.PeerID{p2}, F: 0, diff --git a/core/capabilities/syncer.go b/core/capabilities/syncer.go index dc9126dba36..67d388a8221 100644 --- a/core/capabilities/syncer.go +++ b/core/capabilities/syncer.go @@ -6,6 +6,7 @@ import ( "sync" "time" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/mercury" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/triggers" @@ -70,7 +71,7 @@ func (s *registrySyncer) Start(ctx context.Context) error { "12D3KooWN2hztiXNNS1jMQTTvvPRYcarK1C7T3Mdqk4x4gwyo5WS", } allPeers := make(map[ragetypes.PeerID]p2ptypes.StreamConfig) - addPeersToDONInfo := func(peers []string, donInfo *remotetypes.DON) error { + addPeersToDONInfo := func(peers []string, donInfo *capabilities.DON) error { for _, peerID := range peers { var p ragetypes.PeerID err := p.UnmarshalText([]byte(peerID)) @@ -82,11 +83,11 @@ func (s *registrySyncer) Start(ctx context.Context) error { } return nil } - workflowDonInfo := remotetypes.DON{ID: "workflowDon1", F: 1} + workflowDonInfo := capabilities.DON{ID: "workflowDon1", F: 1} if err := addPeersToDONInfo(workflowDONPeers, &workflowDonInfo); err != nil { return err } - triggerCapabilityDonInfo := remotetypes.DON{ID: "capabilityDon1", F: 1} + triggerCapabilityDonInfo := capabilities.DON{ID: "capabilityDon1", F: 1} if err := addPeersToDONInfo(triggerDONPeers, &triggerCapabilityDonInfo); err != nil { return err } @@ -101,6 +102,7 @@ func (s *registrySyncer) Start(ctx context.Context) error { CapabilityType: commoncap.CapabilityTypeTrigger, Description: "Remote Trigger", Version: "0.0.1", + DON: &triggerCapabilityDonInfo, } myId := s.peerWrapper.GetPeer().ID().String() config := remotetypes.RemoteTriggerConfig{ @@ -125,7 +127,7 @@ func (s *registrySyncer) Start(ctx context.Context) error { } if slices.Contains(triggerDONPeers, myId) { s.lggr.Info("member of a capability DON - starting remote publishers") - workflowDONs := map[string]remotetypes.DON{ + workflowDONs := map[string]capabilities.DON{ workflowDonInfo.ID: workflowDonInfo, } underlying := triggers.NewMercuryTriggerService(1000, s.lggr) diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index 0ac6555aecc..2aebef3f8f7 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -49,6 +49,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2" "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" externalp2p "github.com/smartcontractkit/chainlink/v2/core/services/p2p/wrapper" "github.com/smartcontractkit/chainlink/v2/core/services/periodicbackup" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" @@ -189,9 +190,12 @@ func NewApplication(opts ApplicationOpts) (Application, error) { unrestrictedHTTPClient := opts.UnrestrictedHTTPClient registry := capabilities.NewRegistry(globalLogger) + var externalPeerWrapper p2ptypes.PeerWrapper if cfg.Capabilities().Peering().Enabled() { - externalPeerWrapper := externalp2p.NewExternalPeerWrapper(keyStore.P2P(), cfg.Capabilities().Peering(), globalLogger) - signer := externalPeerWrapper + externalPeer := externalp2p.NewExternalPeerWrapper(keyStore.P2P(), cfg.Capabilities().Peering(), globalLogger) + signer := externalPeer + externalPeerWrapper = externalPeer + srvcs = append(srvcs, externalPeerWrapper) // NOTE: RegistrySyncer will depend on a Relayer when fully implemented @@ -367,16 +371,26 @@ func NewApplication(opts ApplicationOpts) (Application, error) { globalLogger, streamRegistry, pipelineRunner, - cfg.JobPipeline()), - job.Workflow: workflows.NewDelegate( - globalLogger, - registry, - legacyEVMChains, + cfg.JobPipeline(), ), } webhookJobRunner = delegates[job.Webhook].(*webhook.Delegate).WebhookJobRunner() ) + delegates[job.Workflow] = workflows.NewDelegate( + globalLogger, + registry, + legacyEVMChains, + func() *p2ptypes.PeerID { + if externalPeerWrapper == nil { + return nil + } + + peerID := externalPeerWrapper.GetPeer().ID() + return &peerID + }, + ) + // Flux monitor requires ethereum just to boot, silence errors with a null delegate if !cfg.EVMRPCEnabled() { delegates[job.FluxMonitor] = &job.NullDelegate{Type: job.FluxMonitor} diff --git a/core/services/workflows/delegate.go b/core/services/workflows/delegate.go index e22a78212d2..8dc440da477 100644 --- a/core/services/workflows/delegate.go +++ b/core/services/workflows/delegate.go @@ -2,22 +2,26 @@ package workflows import ( "context" + "encoding/hex" "fmt" "github.com/google/uuid" "github.com/pelletier/go-toml" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/types/core" "github.com/smartcontractkit/chainlink/v2/core/capabilities/targets" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) type Delegate struct { registry core.CapabilitiesRegistry logger logger.Logger legacyEVMChains legacyevm.LegacyChainContainer + peerID func() *p2ptypes.PeerID } var _ job.Delegate = (*Delegate)(nil) @@ -42,11 +46,18 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.Ser d.logger.Errorw("could not initialize writes", err) } + dinfo, err := initializeDONInfo(d.logger) + if err != nil { + d.logger.Errorw("could not add initialize don info", err) + } + cfg := Config{ Lggr: d.logger, Spec: spec.WorkflowSpec.Workflow, WorkflowID: spec.WorkflowSpec.WorkflowID, Registry: d.registry, + DONInfo: dinfo, + PeerID: d.peerID, } engine, err := NewEngine(cfg) if err != nil { @@ -55,8 +66,45 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.Ser return []job.ServiceCtx{engine}, nil } -func NewDelegate(logger logger.Logger, registry core.CapabilitiesRegistry, legacyEVMChains legacyevm.LegacyChainContainer) *Delegate { - return &Delegate{logger: logger, registry: registry, legacyEVMChains: legacyEVMChains} +func initializeDONInfo(lggr logger.Logger) (*capabilities.DON, error) { + var key [16]byte + + // TODO: fetch the key and DONInfo from the registry + keyString := "44fb5c1ee8ee48846c808a383da3aba3" + k, err := hex.DecodeString(keyString) + if err != nil { + lggr.Errorf("could not decode key %s: %w", keyString, err) + } + key = [16]byte(k) + + p2pStrings := []string{ + "12D3KooWBCF1XT5Wi8FzfgNCqRL76Swv8TRU3TiD4QiJm8NMNX7N", + "12D3KooWG1AyvwmCpZ93J8pBQUE1SuzrjDXnT4BeouncHR3jWLCG", + "12D3KooWGeUKZBRMbx27FUTgBwZa9Ap9Ym92mywwpuqkEtz8XWyv", + "12D3KooW9zYWQv3STmDeNDidyzxsJSTxoCTLicafgfeEz9nhwhC4", + } + + p2pIDs := []p2ptypes.PeerID{} + for _, p := range p2pStrings { + pid := p2ptypes.PeerID{} + err := pid.UnmarshalText([]byte(p)) + if err != nil { + return nil, err + } + + p2pIDs = append(p2pIDs, pid) + } + + return &capabilities.DON{ + Members: p2pIDs, + Config: capabilities.DONConfig{ + SharedSecret: key, + }, + }, nil +} + +func NewDelegate(logger logger.Logger, registry core.CapabilitiesRegistry, legacyEVMChains legacyevm.LegacyChainContainer, peerID func() *p2ptypes.PeerID) *Delegate { + return &Delegate{logger: logger, registry: registry, legacyEVMChains: legacyEVMChains, peerID: peerID} } func ValidatedWorkflowSpec(tomlString string) (job.Job, error) { diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index 052c2c86647..0ecc311acac 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -13,6 +13,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types/core" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/v2/core/logger" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) const ( @@ -21,12 +22,18 @@ const ( mockedWorkflowID = "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" ) +type donInfo struct { + *capabilities.DON + PeerID func() *p2ptypes.PeerID +} + // Engine handles the lifecycle of a single workflow and its executions. type Engine struct { services.StateMachine logger logger.Logger registry core.CapabilitiesRegistry workflow *workflow + donInfo donInfo executionStates *inMemoryStore pendingStepRequests chan stepRequest triggerEvents chan capabilities.CapabilityResponse @@ -88,7 +95,11 @@ LOOP: continue } - // Walk the graph and register each step's capability to this workflow + // Walk the graph and initialize each step. + // This means: + // - fetching the capability + // - register the capability to this workflow + // - initializing the step's executionStrategy err := e.workflow.walkDo(keywordTrigger, func(s *step) error { // The graph contains a dummy step for triggers, but // we handle triggers separately since there might be more than one. @@ -96,45 +107,12 @@ LOOP: return nil } - // If the capability already exists, that means we've already registered it - if s.capability != nil { - return nil - } - - cp, innerErr := e.registry.Get(ctx, s.Type) - if innerErr != nil { - return fmt.Errorf("failed to get capability with ref %s: %s, retrying in %d seconds", s.Type, innerErr, retrySec) - } - - // We only need to configure actions, consensus and targets here, and - // they all satisfy the `CallbackExecutable` interface - cc, ok := cp.(capabilities.CallbackExecutable) - if !ok { - return fmt.Errorf("could not coerce capability %s to CallbackExecutable", s.Type) - } - - if s.config == nil { - configMap, ierr := values.NewMap(s.Config) - if ierr != nil { - return fmt.Errorf("failed to convert config to values.Map: %s", ierr) - } - s.config = configMap - } - - reg := capabilities.RegisterToWorkflowRequest{ - Metadata: capabilities.RegistrationMetadata{ - WorkflowID: e.workflow.id, - }, - Config: s.config, - } - - innerErr = cc.RegisterToWorkflow(ctx, reg) - if innerErr != nil { - return fmt.Errorf("failed to register to workflow (%+v): %w", reg, innerErr) + err := e.initializeCapability(ctx, s, retrySec) + if err != nil { + return err } - s.capability = cc - return nil + return e.initializeExecutionStrategy(s) }) if err != nil { initSuccessful = false @@ -158,6 +136,101 @@ LOOP: e.logger.Info("engine initialized") } +func (e *Engine) initializeCapability(ctx context.Context, s *step, retrySec int) error { + // If the capability already exists, that means we've already registered it + if s.capability != nil { + return nil + } + + cp, innerErr := e.registry.Get(ctx, s.Type) + if innerErr != nil { + return fmt.Errorf("failed to get capability with ref %s: %s, retrying in %d seconds", s.Type, innerErr, retrySec) + } + + // We only need to configure actions, consensus and targets here, and + // they all satisfy the `CallbackCapability` interface + cc, ok := cp.(capabilities.CallbackCapability) + if !ok { + return fmt.Errorf("could not coerce capability %s to CallbackCapability", s.Type) + } + + if s.config == nil { + configMap, ierr := values.NewMap(s.Config) + if ierr != nil { + return fmt.Errorf("failed to convert config to values.Map: %s", ierr) + } + s.config = configMap + } + + reg := capabilities.RegisterToWorkflowRequest{ + Metadata: capabilities.RegistrationMetadata{ + WorkflowID: e.workflow.id, + }, + Config: s.config, + } + + innerErr = cc.RegisterToWorkflow(ctx, reg) + if innerErr != nil { + return fmt.Errorf("failed to register to workflow (%+v): %w", reg, innerErr) + } + + s.capability = cc + return nil +} + +// initializeExecutionStrategy for `step`. +// Broadly speaking, we'll use `immediateExecution` for non-target steps +// and `scheduledExecution` for targets. If we don't have the necessary +// config to initialize a scheduledExecution for a target, we'll fallback to +// using `immediateExecution`. +func (e *Engine) initializeExecutionStrategy(step *step) error { + if step.executionStrategy != nil { + return nil + } + + // If donInfo has no peerID, then the peer wrapper hasn't been initialized. + // Let's error and try again next time around. + if e.donInfo.PeerID() == nil { + return fmt.Errorf("failed to initialize execution strategy: peer ID %s has not been initialized", e.donInfo.PeerID()) + } + + ie := immediateExecution{} + if step.CapabilityType != capabilities.CapabilityTypeTarget { + e.logger.Debugf("initializing step %+v with immediate execution strategy: not a target", step) + step.executionStrategy = ie + return nil + } + + dinfo := e.donInfo + if dinfo.DON == nil { + e.logger.Debugf("initializing target step with immediate execution strategy: donInfo %+v", e.donInfo) + step.executionStrategy = ie + return nil + } + + var position *int + for i, w := range dinfo.Members { + if w == *dinfo.PeerID() { + idx := i + position = &idx + } + } + + if position == nil { + e.logger.Debugf("initializing step %+v with immediate execution strategy: position not found in donInfo %+v", step, e.donInfo) + step.executionStrategy = ie + return nil + } + + step.executionStrategy = scheduledExecution{ + DON: e.donInfo.DON, + Position: *position, + PeerID: e.donInfo.PeerID(), + } + e.logger.Debugf("initializing step %+v with scheduled execution strategy", step) + return nil +} + // registerTrigger is used during the initialization phase to bind a trigger to this workflow func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability) error { triggerInputs, err := values.NewMap( @@ -436,20 +509,24 @@ func (e *Engine) workerForStepRequest(ctx context.Context, msg stepRequest) { defer func() { e.newWorkerCh <- struct{}{} }() defer e.wg.Done() - e.logger.Debugw("executing on a step event", "stepRef", msg.stepRef, "executionID", msg.state.executionID) + // Instantiate a child logger; in addition to the WorkflowID field the workflow + // logger will already have, this adds the `stepRef` and `executionID` + l := e.logger.With("stepRef", msg.stepRef, "executionID", msg.state.executionID) + + l.Debugw("executing on a step event") stepState := &stepState{ outputs: &stepOutput{}, executionID: msg.state.executionID, ref: msg.stepRef, } - inputs, outputs, err := e.executeStep(ctx, msg) + inputs, outputs, err := e.executeStep(ctx, l, msg) if err != nil { - e.logger.Errorf("error executing step request: %s", err, "executionID", msg.state.executionID, "stepRef", msg.stepRef) + l.Errorf("error executing step request: %s", err) stepState.outputs.err = err stepState.status = statusErrored } else { - e.logger.Infow("step executed successfully", "executionID", msg.state.executionID, "stepRef", msg.stepRef, "outputs", outputs) + l.Infow("step executed successfully", "outputs", outputs) stepState.outputs.value = outputs stepState.status = statusCompleted } @@ -464,13 +541,13 @@ func (e *Engine) workerForStepRequest(ctx context.Context, msg stepRequest) { // like this one will get picked up again and will be reprocessed. select { case <-ctx.Done(): - e.logger.Errorf("context canceled before step update could be issued", err, "executionID", msg.state.executionID, "stepRef", msg.stepRef) + l.Errorf("context canceled before step update could be issued", err) case e.stepUpdateCh <- *stepState: } } // executeStep executes the referenced capability within a step and returns the result. -func (e *Engine) executeStep(ctx context.Context, msg stepRequest) (*values.Map, values.Value, error) { +func (e *Engine) executeStep(ctx context.Context, l logger.Logger, msg stepRequest) (*values.Map, values.Value, error) { step, err := e.workflow.Vertex(msg.stepRef) if err != nil { return nil, nil, err @@ -495,18 +572,12 @@ func (e *Engine) executeStep(ctx context.Context, msg stepRequest) (*values.Map, }, } - resp, err := capabilities.ExecuteSync(ctx, step.capability, tr) + output, err := step.executionStrategy.Apply(ctx, l, step.capability, tr) if err != nil { return inputs, nil, err } - // `ExecuteSync` returns a `values.List` even if there was - // just one return value. If that is the case, let's unwrap the - // single value to make it easier to use in -- for example -- variable interpolation. - if len(resp.Underlying) > 1 { - return inputs, resp, err - } - return inputs, resp.Underlying[0], err + return inputs, output, err } func (e *Engine) deregisterTrigger(ctx context.Context, t *triggerCapability) error { @@ -595,6 +666,8 @@ type Config struct { MaxWorkerLimit int QueueSize int NewWorkerTimeout time.Duration + DONInfo *capabilities.DON + PeerID func() *p2ptypes.PeerID } const ( @@ -638,9 +711,13 @@ func NewEngine(cfg Config) (engine *Engine, err error) { } engine = &Engine{ - logger: cfg.Lggr.Named("WorkflowEngine"), - registry: cfg.Registry, - workflow: workflow, + logger: cfg.Lggr.Named("WorkflowEngine").With("workflowID", cfg.WorkflowID), + registry: cfg.Registry, + workflow: workflow, + donInfo: donInfo{ + DON: cfg.DONInfo, + PeerID: cfg.PeerID, + }, executionStates: newInMemoryStore(), pendingStepRequests: make(chan stepRequest, cfg.QueueSize), newWorkerCh: newWorkerCh, diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index 448ff13ec79..d82c9d4b7d2 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -14,6 +14,7 @@ import ( coreCap "github.com/smartcontractkit/chainlink/v2/core/capabilities" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) const hardcodedWorkflow = ` @@ -148,10 +149,13 @@ func TestEngineWithHardcodedWorkflow(t *testing.T) { require.NoError(t, reg.Add(ctx, target2)) lggr := logger.TestLogger(t) + peerID := p2ptypes.PeerID{} cfg := Config{ Lggr: lggr, Registry: reg, Spec: hardcodedWorkflow, + DONInfo: nil, + PeerID: func() *p2ptypes.PeerID { return &peerID }, } eng, err := NewEngine(cfg) require.NoError(t, err) @@ -308,10 +312,13 @@ func TestEngine_ErrorsTheWorkflowIfAStepErrors(t *testing.T) { require.NoError(t, reg.Add(ctx, mockFailingConsensus())) require.NoError(t, reg.Add(ctx, mockTarget())) + peerID := p2ptypes.PeerID{} cfg := Config{ Lggr: logger.TestLogger(t), Registry: reg, Spec: simpleWorkflow, + DONInfo: nil, + PeerID: func() *p2ptypes.PeerID { return &peerID }, } eng, err := NewEngine(cfg) require.NoError(t, err) @@ -413,10 +420,13 @@ func TestEngine_MultiStepDependencies(t *testing.T) { action, out := mockAction() require.NoError(t, reg.Add(ctx, action)) + peerID := p2ptypes.PeerID{} cfg := Config{ Lggr: logger.TestLogger(t), Registry: reg, Spec: multiStepWorkflow, + DONInfo: nil, + PeerID: func() *p2ptypes.PeerID { return &peerID }, } eng, err := NewEngine(cfg) require.NoError(t, err) diff --git a/core/services/workflows/execution_strategy.go b/core/services/workflows/execution_strategy.go new file mode 100644 index 00000000000..f5da8bca4be --- /dev/null +++ b/core/services/workflows/execution_strategy.go @@ -0,0 +1,171 @@ +package workflows + +import ( + "context" + "fmt" + "time" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/logger" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" + + "github.com/smartcontractkit/libocr/permutation" + + "golang.org/x/crypto/sha3" +) + +type executionStrategy interface { + Apply(ctx context.Context, l logger.Logger, cap capabilities.CallbackCapability, req capabilities.CapabilityRequest) (values.Value, error) +} + +var _ executionStrategy = immediateExecution{} + +type immediateExecution struct{} + +func (i immediateExecution) Apply(ctx context.Context, lggr logger.Logger, cap capabilities.CallbackCapability, req capabilities.CapabilityRequest) (values.Value, error) { + l, err := capabilities.ExecuteSync(ctx, cap, req) + if err != nil { + return nil, err + } + + // `ExecuteSync` returns a `values.List` even if there was + // just one return value. If that is the case, let's unwrap the + // single value to make it easier to use in -- for example -- variable interpolation. + if len(l.Underlying) > 1 { + return l, nil + } + + return l.Underlying[0], nil +} + +var _ executionStrategy = scheduledExecution{} + +type scheduledExecution struct { + DON *capabilities.DON + PeerID *p2ptypes.PeerID + Position int +} + +var ( + // S = [N] + Schedule_AllAtOnce = "allAtOnce" + // S = [1 * N] + Schedule_OneAtATime = "oneAtATime" +) + +// scheduledExecution generates a pseudo-random transmission schedule, +// and delays execution until a node is required to transmit. +func (d scheduledExecution) Apply(ctx context.Context, lggr logger.Logger, cap capabilities.CallbackCapability, req capabilities.CapabilityRequest) (values.Value, error) { + tc, err := d.transmissionConfig(req.Config) + if err != nil { + return nil, err + } + + info, err := cap.Info(ctx) + if err != nil { + return nil, err + } + + switch { + // Case 1: Local DON + case info.DON == nil: + n := len(d.DON.Members) + key := d.key(d.DON.Config.SharedSecret, req.Metadata.WorkflowID, req.Metadata.WorkflowExecutionID) + sched, err := schedule(tc.Schedule, n) + if err != nil { + return nil, err + } + + picked := permutation.Permutation(n, key) + delay := d.delayFor(d.Position, sched, picked, tc.DeltaStage) + if delay == nil { + lggr.Debugw("skipping transmission: node is not included in schedule") + return nil, nil + } + + lggr.Debugf("execution delayed by %+v", *delay) + select { + case <-ctx.Done(): + return nil, ctx.Err() + case <-time.After(*delay): + lggr.Debugw("executing delayed execution") + return immediateExecution{}.Apply(ctx, lggr, cap, req) + } + // Case 2: Remote DON + default: + // TODO: fill in the remote DON case once consensus has been reach on what to do. + lggr.Debugw("remote DON transmission not implemented: using immediate execution") + return immediateExecution{}.Apply(ctx, lggr, cap, req) + } +} + +// `key` uses a shared secret, combined with a workflowID and a workflowExecutionID to generate +// a secret that can later be used to pseudo-randomly determine a schedule for a set of nodes in a DON. +// The addition of the workflowExecutionID -- which nodes don't know ahead of time -- additionally guarantees +// that a malicious coalition of nodes can't "game" the schedule. +// IMPORTANT: changing this function should happen carefully to maintain the guarantee that all nodes +// arrive at the same secret. +func (d scheduledExecution) key(sharedSecret [16]byte, workflowID, workflowExecutionID string) [16]byte { + hash := sha3.NewLegacyKeccak256() + hash.Write(sharedSecret[:]) + hash.Write([]byte(workflowID)) + hash.Write([]byte(workflowExecutionID)) + + var key [16]byte + copy(key[:], hash.Sum(nil)) + return key +} + +type transmissionConfig struct { + Schedule string + DeltaStage time.Duration +} + +func (d scheduledExecution) transmissionConfig(config *values.Map) (transmissionConfig, error) { + var tc struct { + DeltaStage string + Schedule string + } + err := config.UnwrapTo(&tc) + if err != nil { + return transmissionConfig{}, err + } + + duration, err := time.ParseDuration(tc.DeltaStage) + if err != nil { + return transmissionConfig{}, fmt.Errorf("failed to parse DeltaStage %s as duration: %w", tc.DeltaStage, err) + } + + return transmissionConfig{ + Schedule: tc.Schedule, + DeltaStage: duration, + }, nil +} + +func (d scheduledExecution) delayFor(position int, schedule []int, permutation []int, deltaStage time.Duration) *time.Duration { + sum := 0 + for i, s := range schedule { + sum += s + if permutation[position] < sum { + result := time.Duration(i) * deltaStage + return &result + } + } + + return nil +} + +func schedule(sched string, N int) ([]int, error) { + switch sched { + case Schedule_AllAtOnce: + return []int{N}, nil + case Schedule_OneAtATime: + sch := []int{} + for i := 0; i < N; i++ { + sch = append(sch, 1) + } + return sch, nil + } + return nil, fmt.Errorf("unknown schedule %s", sched) +} diff --git a/core/services/workflows/execution_strategy_test.go b/core/services/workflows/execution_strategy_test.go new file mode 100644 index 00000000000..bdf782c87b9 --- /dev/null +++ b/core/services/workflows/execution_strategy_test.go @@ -0,0 +1,170 @@ +package workflows + +import ( + "crypto/rand" + "encoding/hex" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/logger" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" +) + +func assertBetween(t *testing.T, got time.Duration, low time.Duration, high time.Duration) { + assert.GreaterOrEqual(t, got, low) + assert.LessOrEqual(t, got, high) +} + +func TestScheduledExecutionStrategy_LocalDON(t *testing.T) { + var gotTime time.Time + var called bool + + // Our capability has DONInfo == nil, so we'll treat it as a local + // capability and use the local DON Info to determine the transmission + // schedule. + mt := newMockCapability( + capabilities.MustNewCapabilityInfo( + "write_polygon-testnet-mumbai", + capabilities.CapabilityTypeTarget, + "a write capability targeting polygon mumbai testnet", + "v1.0.0", + nil, + ), + func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { + gotTime = time.Now() + called = true + return capabilities.CapabilityResponse{}, nil + }, + ) + + l := logger.TestLogger(t) + + // The combination of this key and the metadata above + // will yield the permutation [3, 2, 0, 1] + key, err := hex.DecodeString("fb13ca015a9ec60089c7141e9522de79") + require.NoError(t, err) + + testCases := []struct { + name string + position int + schedule string + low time.Duration + high time.Duration + }{ + { + name: "position 0; oneAtATime", + position: 0, + schedule: "oneAtATime", + low: 300 * time.Millisecond, + high: 400 * time.Millisecond, + }, + { + name: "position 1; oneAtATime", + position: 1, + schedule: "oneAtATime", + low: 200 * time.Millisecond, + high: 300 * time.Millisecond, + }, + { + name: "position 2; oneAtATime", + position: 2, + schedule: "oneAtATime", + low: 0 * time.Millisecond, + high: 100 * time.Millisecond, + }, + { + name: "position 3; oneAtATime", + position: 3, + schedule: "oneAtATime", + low: 100 * time.Millisecond, + high: 200 * time.Millisecond, + }, + { + name: "position 0; allAtOnce", + position: 0, + schedule: "allAtOnce", + low: 0 * time.Millisecond, + high: 100 * time.Millisecond, + }, + { + name: "position 1; allAtOnce", + position: 1, + schedule: "allAtOnce", + low: 0 * time.Millisecond, + high: 100 * time.Millisecond, + }, + { + name: "position 2; allAtOnce", + position: 2, + schedule: "allAtOnce", + low: 0 * time.Millisecond, + high: 100 * time.Millisecond, + }, + { + name: "position 3; allAtOnce", + position: 3, + schedule: "allAtOnce", + low: 0 * time.Millisecond, + high: 100 * time.Millisecond, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + startTime := time.Now() + + m, err := values.NewMap(map[string]any{ + "schedule": tc.schedule, + "deltaStage": "100ms", + }) + require.NoError(t, err) + + req := capabilities.CapabilityRequest{ + Config: m, + Metadata: capabilities.RequestMetadata{ + WorkflowID: "mock-workflow-id", + WorkflowExecutionID: "mock-execution-id", + }, + } + + ids := []p2ptypes.PeerID{ + randKey(), + randKey(), + randKey(), + randKey(), + } + don := &capabilities.DON{ + Members: ids, + Config: capabilities.DONConfig{ + SharedSecret: [16]byte(key), + }, + } + peerID := ids[tc.position] + de := scheduledExecution{ + DON: don, + PeerID: &peerID, + Position: tc.position, + } + _, err = de.Apply(tests.Context(t), l, mt, req) + require.NoError(t, err) + require.True(t, called) + + assertBetween(t, gotTime.Sub(startTime), tc.low, tc.high) + }) + } +} + +func randKey() [32]byte { + key := make([]byte, 32) + _, err := rand.Read(key) + if err != nil { + panic(err) + } + return [32]byte(key) +} diff --git a/core/services/workflows/models.go b/core/services/workflows/models.go index e6c92a641e4..92abf36d2c0 100644 --- a/core/services/workflows/models.go +++ b/core/services/workflows/models.go @@ -19,10 +19,13 @@ type stepRequest struct { // // Within the workflow spec, they are called "Capability Properties". type stepDefinition struct { + // TODO: Rename this, type here refers to the capability ID, not its type. Type string `json:"type" jsonschema:"required"` Ref string `json:"ref,omitempty" jsonschema:"pattern=^[a-z0-9_]+$"` Inputs map[string]any `json:"inputs,omitempty"` Config map[string]any `json:"config" jsonschema:"required"` + + CapabilityType capabilities.CapabilityType `json:"-"` } // workflowSpec is the parsed representation of a workflow. @@ -106,9 +109,10 @@ func (w *workflow) dependents(start string) ([]*step, error) { // step wraps a stepDefinition with additional context for dependencies and execution type step struct { stepDefinition - dependencies []string - capability capabilities.CallbackExecutable - config *values.Map + dependencies []string + capability capabilities.CallbackCapability + config *values.Map + executionStrategy executionStrategy } type triggerCapability struct { diff --git a/core/services/workflows/models_yaml.go b/core/services/workflows/models_yaml.go index 396811c3729..3d65e24a814 100644 --- a/core/services/workflows/models_yaml.go +++ b/core/services/workflows/models_yaml.go @@ -10,6 +10,8 @@ import ( "github.com/invopop/jsonschema" "github.com/shopspring/decimal" "sigs.k8s.io/yaml" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" ) func GenerateJsonSchema() ([]byte, error) { @@ -47,22 +49,30 @@ type workflowSpecYaml struct { func (w workflowSpecYaml) toWorkflowSpec() workflowSpec { triggers := make([]stepDefinition, 0, len(w.Triggers)) for _, t := range w.Triggers { - triggers = append(triggers, t.toStepDefinition()) + sd := t.toStepDefinition() + sd.CapabilityType = capabilities.CapabilityTypeTrigger + triggers = append(triggers, sd) } actions := make([]stepDefinition, 0, len(w.Actions)) for _, a := range w.Actions { - actions = append(actions, a.toStepDefinition()) + sd := a.toStepDefinition() + sd.CapabilityType = capabilities.CapabilityTypeAction + actions = append(actions, sd) } consensus := make([]stepDefinition, 0, len(w.Consensus)) for _, c := range w.Consensus { - consensus = append(consensus, c.toStepDefinition()) + sd := c.toStepDefinition() + sd.CapabilityType = capabilities.CapabilityTypeConsensus + consensus = append(consensus, sd) } targets := make([]stepDefinition, 0, len(w.Targets)) for _, t := range w.Targets { - targets = append(targets, t.toStepDefinition()) + sd := t.toStepDefinition() + sd.CapabilityType = capabilities.CapabilityTypeTarget + targets = append(targets, sd) } return workflowSpec{ diff --git a/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2_spec.json b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2_spec.json index dfa13449a48..f4024e24267 100644 --- a/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2_spec.json +++ b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2_spec.json @@ -28,4 +28,4 @@ "config": {} } ] -} \ No newline at end of file +} From 1d9dd466e2933b7558949554b882f29f63d90b9f Mon Sep 17 00:00:00 2001 From: Domino Valdano Date: Thu, 25 Apr 2024 18:39:18 -0700 Subject: [PATCH 22/34] Make LogPoller more robust against local finality violations (#12605) * Reduce unnecessary code duplication getCurrentBlockMaybeHandleReorg is called just before the for loop over unfinalized blocks begins, and at the end of each iteration. Simplifying by moving them both to the beginning of the for loop * Fix bugs in TestLogPoller_BackupPollAndSaveLogsSkippingLogsThatAreTooOld This fixes 2 bugs on develop branch in this test, and removes some unused commented code. First Bug ========= The first bug was causing a false positive PASS on develop branch, which was obscuring a (very minor) bug in BackupPoller that's been fixed in this PR. The comment here about what the test was intended to test is still correct: // Only the 2nd batch + 1 log from a previous batch should be backfilled, because we perform backfill starting // from one block behind the latest finalized block Contrary to the comment, the code was returning 2 logs from the 1st batch (Data=9 & Data=10), plus 9 of 10 logs from the 2nd batch. This was incorrect behavior, but the test was also checking for the same incorrect behavior (looking for 11 logs with first one being Data=9) instead of what's described in the comment. The bug in the production code was that it starts the Backup Poller at Finalized - 1 instead of Finalized. This is a harmless "bug", just unnecessarily starting a block too early, since there's no reason for backup logpoller to re-request the same finalized logs that's already been processed. Now, the code returns the last log from the 1st batch + all but one logs from the 2nd batch, which is correct. (It can't return the last log because that goes beyond the last safe block.) So the test checks that there are 10 logs with first one being Data=10 (last log from the first batch.) Second Bug ========== The second bug was passing firstBatchBlock and secondBatchBlock directly to markBlockAsFinalized() instead of passing firstBatchBlock - 1 and secondBatchBlock - 1. This was only working because of a bug in the version of geth we're currently using: when you request the pending block from simulated geth, it gives you back the current block (1 block prior) instead of the current block. (For example, in the first case, even though we wanted block 11, the latest current block, we request block 12 and get back block 11.) This has been fixed in the latest version of geth... so presumably if we don't fix this here the test would have started failing as soon as we upgrade to the latest version of geth. It doesn't change any behavior of the test for the present version of geth, just makes it more clear that we want block 11 not 12. * Check that all results from batchFetchBlocks() are finalized aside from "latest" batchFetchBlocks() will now fetch the "finalized" block along with the rest of each batch, and validate that all of the block numbers (aside from the special when "lateest" is requested) are <= the finalized block number returned. Also, change backfill() to always save the last block of each batch of logs requested, rather than the last block of the logs returned. This only makes a difference if the last block requested has no logs matching the filter, but this change is essential for being able to safely change lastSafeBlockNumber from latestFinalizedBlock - 1 to latestFinalizedBlock * Update logpoller tests * fix merge conflict * reduce cognitive complexity * Add validationReqType type definition * Fix comments * Add Test_FetchBlocks --- .changeset/fresh-moles-explode.md | 5 + core/chains/evm/logpoller/log_poller.go | 189 +++++++++++++----- .../evm/logpoller/log_poller_internal_test.go | 136 ++++++++++++- core/chains/evm/logpoller/log_poller_test.go | 49 ++--- 4 files changed, 290 insertions(+), 89 deletions(-) create mode 100644 .changeset/fresh-moles-explode.md diff --git a/.changeset/fresh-moles-explode.md b/.changeset/fresh-moles-explode.md new file mode 100644 index 00000000000..205002b40a0 --- /dev/null +++ b/.changeset/fresh-moles-explode.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +core/chains/evm/logpoller: Stricter finality checks in LogPoller, to be more robust during rpc failover events #updated diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go index de2a182bbce..7592ec104c4 100644 --- a/core/chains/evm/logpoller/log_poller.go +++ b/core/chains/evm/logpoller/log_poller.go @@ -699,8 +699,8 @@ func (lp *logPoller) BackupPollAndSaveLogs(ctx context.Context) { } return } - // If this is our first run, start from block min(lastProcessed.FinalizedBlockNumber-1, lastProcessed.BlockNumber-backupPollerBlockDelay) - backupStartBlock := mathutil.Min(lastProcessed.FinalizedBlockNumber-1, lastProcessed.BlockNumber-lp.backupPollerBlockDelay) + // If this is our first run, start from block min(lastProcessed.FinalizedBlockNumber, lastProcessed.BlockNumber-backupPollerBlockDelay) + backupStartBlock := mathutil.Min(lastProcessed.FinalizedBlockNumber, lastProcessed.BlockNumber-lp.backupPollerBlockDelay) // (or at block 0 if whole blockchain is too short) lp.backupPollerNextBlock = mathutil.Max(backupStartBlock, 0) } @@ -771,11 +771,16 @@ func convertTopics(topics []common.Hash) [][]byte { return topicsForDB } -func (lp *logPoller) blocksFromLogs(ctx context.Context, logs []types.Log) (blocks []LogPollerBlock, err error) { +// blocksFromLogs fetches all of the blocks associated with a given list of logs. It will also unconditionally fetch endBlockNumber, +// whether or not there are any logs in the list from that block +func (lp *logPoller) blocksFromLogs(ctx context.Context, logs []types.Log, endBlockNumber uint64) (blocks []LogPollerBlock, err error) { var numbers []uint64 for _, log := range logs { numbers = append(numbers, log.BlockNumber) } + if numbers[len(numbers)-1] != endBlockNumber { + numbers = append(numbers, endBlockNumber) + } return lp.GetBlocksRange(ctx, numbers) } @@ -789,6 +794,7 @@ func (lp *logPoller) backfill(ctx context.Context, start, end int64) error { batchSize := lp.backfillBatchSize for from := start; from <= end; from += batchSize { to := mathutil.Min(from+batchSize-1, end) + gethLogs, err := lp.ec.FilterLogs(ctx, lp.Filter(big.NewInt(from), big.NewInt(to), nil)) if err != nil { var rpcErr client.JsonError @@ -810,13 +816,19 @@ func (lp *logPoller) backfill(ctx context.Context, start, end int64) error { if len(gethLogs) == 0 { continue } - blocks, err := lp.blocksFromLogs(ctx, gethLogs) + blocks, err := lp.blocksFromLogs(ctx, gethLogs, uint64(to)) if err != nil { return err } + endblock := blocks[len(blocks)-1] + if gethLogs[len(gethLogs)-1].BlockNumber != uint64(to) { + // Pop endblock if there were no logs for it, so that length of blocks & gethLogs are the same to pass to convertLogs + blocks = blocks[:len(blocks)-1] + } + lp.lggr.Debugw("Backfill found logs", "from", from, "to", to, "logs", len(gethLogs), "blocks", blocks) - err = lp.orm.InsertLogsWithBlock(ctx, convertLogs(gethLogs, blocks, lp.lggr, lp.ec.ConfiguredChainID()), blocks[len(blocks)-1]) + err = lp.orm.InsertLogsWithBlock(ctx, convertLogs(gethLogs, blocks, lp.lggr, lp.ec.ConfiguredChainID()), endblock) if err != nil { lp.lggr.Warnw("Unable to insert logs, retrying", "err", err, "from", from, "to", to) return err @@ -955,19 +967,18 @@ func (lp *logPoller) PollAndSaveLogs(ctx context.Context, currentBlockNumber int currentBlockNumber = lastSafeBackfillBlock + 1 } - if currentBlockNumber > currentBlock.Number { - // If we successfully backfilled we have logs up to and including lastSafeBackfillBlock, - // now load the first unfinalized block. - currentBlock, err = lp.getCurrentBlockMaybeHandleReorg(ctx, currentBlockNumber, nil) - if err != nil { - // If there's an error handling the reorg, we can't be sure what state the db was left in. - // Resume from the latest block saved. - lp.lggr.Errorw("Unable to get current block", "err", err) - return + for { + if currentBlockNumber > currentBlock.Number { + currentBlock, err = lp.getCurrentBlockMaybeHandleReorg(ctx, currentBlockNumber, nil) + if err != nil { + // If there's an error handling the reorg, we can't be sure what state the db was left in. + // Resume from the latest block saved. + lp.lggr.Errorw("Unable to get current block", "err", err) + return + } + currentBlockNumber = currentBlock.Number } - } - for { h := currentBlock.Hash var logs []types.Log logs, err = lp.ec.FilterLogs(ctx, lp.Filter(nil, nil, &h)) @@ -992,14 +1003,6 @@ func (lp *logPoller) PollAndSaveLogs(ctx context.Context, currentBlockNumber int if currentBlockNumber > latestBlockNumber { break } - currentBlock, err = lp.getCurrentBlockMaybeHandleReorg(ctx, currentBlockNumber, nil) - if err != nil { - // If there's an error handling the reorg, we can't be sure what state the db was left in. - // Resume from the latest block saved. - lp.lggr.Errorw("Unable to get current block", "err", err) - return - } - currentBlockNumber = currentBlock.Number } } @@ -1252,12 +1255,16 @@ func (lp *logPoller) GetBlocksRange(ctx context.Context, numbers []uint64) ([]Lo return blocks, nil } +// fillRemainingBlocksFromRPC sends a batch request for each block in blocksRequested, and converts them from +// geth blocks into LogPollerBlock structs. This is only intended to be used for requesting finalized blocks, +// if any of the blocks coming back are not finalized, an error will be returned func (lp *logPoller) fillRemainingBlocksFromRPC( ctx context.Context, blocksRequested map[uint64]struct{}, blocksFound map[uint64]LogPollerBlock, ) (map[uint64]LogPollerBlock, error) { var remainingBlocks []string + for num := range blocksRequested { if _, ok := blocksFound[num]; !ok { remainingBlocks = append(remainingBlocks, hexutil.EncodeBig(new(big.Int).SetUint64(num))) @@ -1287,54 +1294,126 @@ func (lp *logPoller) fillRemainingBlocksFromRPC( return logPollerBlocks, nil } -func (lp *logPoller) batchFetchBlocks(ctx context.Context, blocksRequested []string, batchSize int64) ([]*evmtypes.Head, error) { - reqs := make([]rpc.BatchElem, 0, len(blocksRequested)) - for _, num := range blocksRequested { - req := rpc.BatchElem{ - Method: "eth_getBlockByNumber", - Args: []interface{}{num, false}, - Result: &evmtypes.Head{}, - } - reqs = append(reqs, req) +// newBlockReq constructs an eth_getBlockByNumber request for particular block number +func newBlockReq(num string) rpc.BatchElem { + return rpc.BatchElem{ + Method: "eth_getBlockByNumber", + Args: []interface{}{num, false}, + Result: &evmtypes.Head{}, } +} - for i := 0; i < len(reqs); i += int(batchSize) { - j := i + int(batchSize) - if j > len(reqs) { - j = len(reqs) - } +type blockValidationType string - err := lp.ec.BatchCallContext(ctx, reqs[i:j]) - if err != nil { - return nil, err +var ( + latestBlock blockValidationType = blockValidationType(rpc.LatestBlockNumber.String()) + finalizedBlock blockValidationType = blockValidationType(rpc.FinalizedBlockNumber.String()) +) + +// fetchBlocks fetches a list of blocks in a single batch. validationReq is the string to use for the +// additional validation request (either the "finalized" or "latest" string defined in rpc module), which +// will be used to validate the finality of the other blocks. +func (lp *logPoller) fetchBlocks(ctx context.Context, blocksRequested []string, validationReq blockValidationType) (blocks []*evmtypes.Head, err error) { + n := len(blocksRequested) + blocks = make([]*evmtypes.Head, 0, n+1) + reqs := make([]rpc.BatchElem, 0, n+1) + + validationBlockIndex := n + for k, num := range blocksRequested { + if num == string(validationReq) { + validationBlockIndex = k } + reqs = append(reqs, newBlockReq(num)) + } + + if validationBlockIndex == n { + // Add validation req if it wasn't in there already + reqs = append(reqs, newBlockReq(string(validationReq))) + } + + err = lp.ec.BatchCallContext(ctx, reqs) + if err != nil { + return nil, err } - var blocks = make([]*evmtypes.Head, 0, len(reqs)) - for _, r := range reqs { - if r.Error != nil { - return nil, r.Error + validationBlock, err := validateBlockResponse(reqs[validationBlockIndex]) + if err != nil { + return nil, err + } + latestFinalizedBlockNumber := validationBlock.Number + if validationReq == latestBlock { + // subtract finalityDepth from "latest" to get finalized, when useFinalityTags = false + latestFinalizedBlockNumber = mathutil.Max(latestFinalizedBlockNumber-lp.finalityDepth, 0) + } + if len(reqs) == n+1 { + reqs = reqs[:n] // ignore last req if we added it explicitly for validation + } + + for k, r := range reqs { + if k == validationBlockIndex { + // Already validated this one, just insert it in proper place + blocks = append(blocks, validationBlock) + continue } - block, is := r.Result.(*evmtypes.Head) - if !is { - return nil, pkgerrors.Errorf("expected result to be a %T, got %T", &evmtypes.Head{}, r.Result) + block, err2 := validateBlockResponse(r) + if err2 != nil { + return nil, err2 } - if block == nil { - return nil, pkgerrors.New("invariant violation: got nil block") + + blockRequested := r.Args[0].(string) + if blockRequested != string(latestBlock) && block.Number > latestFinalizedBlockNumber { + return nil, fmt.Errorf( + "Received unfinalized block %d while expecting finalized block (latestFinalizedBlockNumber = %d)", + block.Number, latestFinalizedBlockNumber) } - if block.Hash == (common.Hash{}) { - return nil, pkgerrors.Errorf("missing block hash for block number: %d", block.Number) + + blocks = append(blocks, block) + } + return blocks, nil +} + +func (lp *logPoller) batchFetchBlocks(ctx context.Context, blocksRequested []string, batchSize int64) ([]*evmtypes.Head, error) { + var blocks = make([]*evmtypes.Head, 0, len(blocksRequested)+1) + + validationReq := finalizedBlock + if !lp.useFinalityTag { + validationReq = latestBlock + } + + for i := 0; i < len(blocksRequested); i += int(batchSize) { + j := i + int(batchSize) + if j > len(blocksRequested) { + j = len(blocksRequested) } - if block.Number < 0 { - return nil, pkgerrors.Errorf("expected block number to be >= to 0, got %d", block.Number) + moreBlocks, err := lp.fetchBlocks(ctx, blocksRequested[i:j], validationReq) + if err != nil { + return nil, err } - blocks = append(blocks, block) + blocks = append(blocks, moreBlocks...) } return blocks, nil } +func validateBlockResponse(r rpc.BatchElem) (*evmtypes.Head, error) { + block, is := r.Result.(*evmtypes.Head) + + if !is { + return nil, pkgerrors.Errorf("expected result to be a %T, got %T", &evmtypes.Head{}, r.Result) + } + if block == nil { + return nil, pkgerrors.New("invariant violation: got nil block") + } + if block.Hash == (common.Hash{}) { + return nil, pkgerrors.Errorf("missing block hash for block number: %d", block.Number) + } + if block.Number < 0 { + return nil, pkgerrors.Errorf("expected block number to be >= to 0, got %d", block.Number) + } + return block, nil +} + // IndexedLogsWithSigsExcluding returns the set difference(A-B) of logs with signature sigA and sigB, matching is done on the topics index // // For example, query to retrieve unfulfilled requests by querying request log events without matching fulfillment log events. diff --git a/core/chains/evm/logpoller/log_poller_internal_test.go b/core/chains/evm/logpoller/log_poller_internal_test.go index b6af0f7de5c..4236f0b8ef1 100644 --- a/core/chains/evm/logpoller/log_poller_internal_test.go +++ b/core/chains/evm/logpoller/log_poller_internal_test.go @@ -2,6 +2,7 @@ package logpoller import ( "context" + "errors" "fmt" "math/big" "reflect" @@ -12,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rpc" pkgerrors "github.com/pkg/errors" @@ -205,13 +207,14 @@ func TestLogPoller_BackupPollerStartup(t *testing.T) { chainID := testutils.FixtureChainID db := pgtest.NewSqlxDB(t) orm := NewORM(chainID, db, lggr) + latestBlock := int64(4) - head := evmtypes.Head{Number: 3} + head := evmtypes.Head{Number: latestBlock} events := []common.Hash{EmitterABI.Events["Log1"].ID} log1 := types.Log{ Index: 0, BlockHash: common.Hash{}, - BlockNumber: uint64(3), + BlockNumber: uint64(latestBlock), Topics: events, Address: addr, TxHash: common.HexToHash("0x1234"), @@ -230,20 +233,44 @@ func TestLogPoller_BackupPollerStartup(t *testing.T) { BackfillBatchSize: 3, RpcBatchSize: 2, KeepFinalizedBlocksDepth: 1000, + BackupPollerBlockDelay: 0, } lp := NewLogPoller(orm, ec, lggr, lpOpts) lp.BackupPollAndSaveLogs(ctx) assert.Equal(t, int64(0), lp.backupPollerNextBlock) assert.Equal(t, 1, observedLogs.FilterMessageSnippet("ran before first successful log poller run").Len()) - lp.PollAndSaveLogs(ctx, 3) + lp.PollAndSaveLogs(ctx, latestBlock) lastProcessed, err := lp.orm.SelectLatestBlock(ctx) require.NoError(t, err) - require.Equal(t, int64(3), lastProcessed.BlockNumber) + require.Equal(t, latestBlock, lastProcessed.BlockNumber) lp.BackupPollAndSaveLogs(ctx) - assert.Equal(t, int64(1), lp.backupPollerNextBlock) // Ensure non-negative! + assert.Equal(t, int64(2), lp.backupPollerNextBlock) +} + +func mockBatchCallContext(t *testing.T, ec *evmclimocks.Client) { + ec.On("BatchCallContext", mock.Anything, mock.Anything).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + for _, e := range elems { + var num int64 + block := e.Args[0].(string) + switch block { + case "latest": + num = 8 + case "finalized": + num = 5 + default: + n, err := hexutil.DecodeUint64(block) + require.NoError(t, err) + num = int64(n) + } + result := e.Result.(*evmtypes.Head) + *result = evmtypes.Head{Number: num, Hash: utils.NewHash()} + + } + }) } func TestLogPoller_Replay(t *testing.T) { @@ -269,16 +296,20 @@ func TestLogPoller_Replay(t *testing.T) { } ec := evmclimocks.NewClient(t) - ec.On("HeadByNumber", mock.Anything, mock.Anything).Return(&head, nil) - ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil).Twice() + ec.On("HeadByNumber", mock.Anything, mock.Anything).Return(func(context.Context, *big.Int) (*evmtypes.Head, error) { + headCopy := head + return &headCopy, nil + }) + ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil).Once() ec.On("ConfiguredChainID").Return(chainID, nil) + lpOpts := Opts{ - PollPeriod: time.Hour, + PollPeriod: time.Second, FinalityDepth: 3, BackfillBatchSize: 3, RpcBatchSize: 3, KeepFinalizedBlocksDepth: 20, - BackupPollerBlockDelay: 100, + BackupPollerBlockDelay: 0, } lp := NewLogPoller(orm, ec, lggr, lpOpts) @@ -308,6 +339,8 @@ func TestLogPoller_Replay(t *testing.T) { // Replay() should return error code received from replayComplete t.Run("returns error code on replay complete", func(t *testing.T) { + ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil).Once() + mockBatchCallContext(t, ec) anyErr := pkgerrors.New("any error") done := make(chan struct{}) go func() { @@ -345,6 +378,7 @@ func TestLogPoller_Replay(t *testing.T) { var wg sync.WaitGroup defer func() { wg.Wait() }() ec.On("FilterLogs", mock.Anything, mock.Anything).Once().Return([]types.Log{log1}, nil).Run(func(args mock.Arguments) { + head = evmtypes.Head{Number: 4} wg.Add(1) go func() { defer wg.Done() @@ -371,6 +405,7 @@ func TestLogPoller_Replay(t *testing.T) { ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil).Maybe() // in case task gets delayed by >= 100ms + head = evmtypes.Head{Number: 5} t.Cleanup(lp.reset) servicetest.Run(t, lp) @@ -395,6 +430,8 @@ func TestLogPoller_Replay(t *testing.T) { ec.On("FilterLogs", mock.Anything, mock.Anything).Once().Return([]types.Log{log1}, nil).Run(func(args mock.Arguments) { go func() { defer close(done) + + head = evmtypes.Head{Number: 4} // Restore latest block to 4, so this matches the fromBlock requested select { case lp.replayStart <- 4: case <-ctx.Done(): @@ -405,9 +442,10 @@ func TestLogPoller_Replay(t *testing.T) { lp.cancel() close(pass) }) - ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil).Maybe() // in case task gets delayed by >= 100ms + ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil) t.Cleanup(lp.reset) + head = evmtypes.Head{Number: 5} // Latest block must be > lastProcessed in order for SaveAndPollLogs() to call FilterLogs() servicetest.Run(t, lp) select { @@ -420,6 +458,9 @@ func TestLogPoller_Replay(t *testing.T) { // ReplayAsync should return as soon as replayStart is received t.Run("ReplayAsync success", func(t *testing.T) { t.Cleanup(lp.reset) + head = evmtypes.Head{Number: 5} + ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil) + mockBatchCallContext(t, ec) servicetest.Run(t, lp) lp.ReplayAsync(1) @@ -430,6 +471,7 @@ func TestLogPoller_Replay(t *testing.T) { t.Run("ReplayAsync error", func(t *testing.T) { t.Cleanup(lp.reset) servicetest.Run(t, lp) + head = evmtypes.Head{Number: 4} anyErr := pkgerrors.New("async error") observedLogs.TakeAll() @@ -462,6 +504,9 @@ func TestLogPoller_Replay(t *testing.T) { err = lp.orm.InsertBlock(ctx, head.Hash, head.Number, head.Timestamp, head.Number) require.NoError(t, err) + ec.On("FilterLogs", mock.Anything, mock.Anything).Return([]types.Log{log1}, nil) + mockBatchCallContext(t, ec) + err = lp.Replay(ctx, 1) require.NoError(t, err) }) @@ -554,6 +599,77 @@ func Test_latestBlockAndFinalityDepth(t *testing.T) { }) } +func Test_FetchBlocks(t *testing.T) { + lggr := logger.Test(t) + chainID := testutils.FixtureChainID + db := pgtest.NewSqlxDB(t) + orm := NewORM(chainID, db, lggr) + ctx := testutils.Context(t) + + lpOpts := Opts{ + PollPeriod: time.Hour, + BackfillBatchSize: 2, + RpcBatchSize: 2, + KeepFinalizedBlocksDepth: 50, + FinalityDepth: 3, + } + + ec := evmclimocks.NewClient(t) + mockBatchCallContext(t, ec) // This will return 5 for "finalized" and 8 for "latest" + + cases := []struct { + name string + blocksRequested []string + expectedErr error + }{{ + "successful validation including finalized and latest", + []string{"0x3", "latest", "0x5", "finalized", "0x1"}, + nil, + }, { + "successful validation with all block numbers", + []string{"0x2", "0x5", "0x3", "0x4"}, + nil, + }, { + "finality violation including finalized and latest", + []string{"0x8", "0x2", "latest", "finalized"}, + errors.New("Received unfinalized block 8 while expecting finalized block (latestFinalizedBlockNumber = 5)"), + }, { + "finality violation with all block numbers", + []string{"0x9", "0x2", "finalized", "latest"}, + errors.New("Received unfinalized block 9 while expecting finalized block (latestFinalizedBlockNumber = 5)"), + }} + + lp := NewLogPoller(orm, ec, lggr, lpOpts) + for _, tc := range cases { + for _, lp.useFinalityTag = range []bool{false, true} { + blockValidationReq := latestBlock + if lp.useFinalityTag { + blockValidationReq = finalizedBlock + } + t.Run(fmt.Sprintf("%s where useFinalityTag=%t", tc.name, lp.useFinalityTag), func(t *testing.T) { + blocks, err := lp.fetchBlocks(ctx, tc.blocksRequested, blockValidationReq) + if tc.expectedErr != nil { + require.Equal(t, err.Error(), tc.expectedErr.Error()) + return // PASS + } + require.NoError(t, err) + for i, blockRequested := range tc.blocksRequested { + switch blockRequested { + case string(latestBlock): + assert.Equal(t, int64(8), blocks[i].Number) + case string(finalizedBlock): + assert.Equal(t, int64(5), blocks[i].Number) + default: + blockNum, err2 := hexutil.DecodeUint64(blockRequested) + require.NoError(t, err2) + assert.Equal(t, int64(blockNum), blocks[i].Number) + } + } + }) + } + } +} + func benchmarkFilter(b *testing.B, nFilters, nAddresses, nEvents int) { lggr := logger.Test(b) lpOpts := Opts{ diff --git a/core/chains/evm/logpoller/log_poller_test.go b/core/chains/evm/logpoller/log_poller_test.go index 2096ccf3cf4..74ec41fa85a 100644 --- a/core/chains/evm/logpoller/log_poller_test.go +++ b/core/chains/evm/logpoller/log_poller_test.go @@ -545,8 +545,6 @@ func TestLogPoller_BackupPollAndSaveLogsSkippingLogsThatAreTooOld(t *testing.T) BackupPollerBlockDelay: 1, } th := SetupTH(t, lpOpts) - //header, err := th.Client.HeaderByNumber(ctx, nil) - //require.NoError(t, err) // Emit some logs in blocks for i := 1; i <= logsBatch; i++ { @@ -559,7 +557,7 @@ func TestLogPoller_BackupPollAndSaveLogsSkippingLogsThatAreTooOld(t *testing.T) // 1 -> 2 -> ... -> firstBatchBlock firstBatchBlock := th.PollAndSaveLogs(ctx, 1) // Mark current tip of the chain as finalized (after emitting 10 logs) - markBlockAsFinalized(t, th, firstBatchBlock) + markBlockAsFinalized(t, th, firstBatchBlock-1) // Emit 2nd batch of block for i := 1; i <= logsBatch; i++ { @@ -571,7 +569,7 @@ func TestLogPoller_BackupPollAndSaveLogsSkippingLogsThatAreTooOld(t *testing.T) // 1 -> 2 -> ... -> firstBatchBlock (finalized) -> .. -> firstBatchBlock + emitted logs secondBatchBlock := th.PollAndSaveLogs(ctx, firstBatchBlock) // Mark current tip of the block as finalized (after emitting 20 logs) - markBlockAsFinalized(t, th, secondBatchBlock) + markBlockAsFinalized(t, th, secondBatchBlock-1) // Register filter err := th.LogPoller.RegisterFilter(ctx, logpoller.Filter{ @@ -595,8 +593,8 @@ func TestLogPoller_BackupPollAndSaveLogsSkippingLogsThatAreTooOld(t *testing.T) th.EmitterAddress1, ) require.NoError(t, err) - require.Len(t, logs, logsBatch+1) - require.Equal(t, hexutil.MustDecode(`0x0000000000000000000000000000000000000000000000000000000000000009`), logs[0].Data) + require.Len(t, logs, logsBatch) + require.Equal(t, hexutil.MustDecode(`0x000000000000000000000000000000000000000000000000000000000000000a`), logs[0].Data) } func TestLogPoller_BlockTimestamps(t *testing.T) { @@ -676,6 +674,7 @@ func TestLogPoller_BlockTimestamps(t *testing.T) { require.NoError(t, err) // Logs should have correct timestamps + require.NotZero(t, len(lg1)) b, _ := th.Client.BlockByHash(ctx, lg1[0].BlockHash) t.Log(len(lg1), lg1[0].BlockTimestamp) assert.Equal(t, int64(b.Time()), lg1[0].BlockTimestamp.UTC().Unix(), time1) @@ -1181,6 +1180,7 @@ func TestLogPoller_PollAndSaveLogsDeepReorg(t *testing.T) { // Check that L1_1 has a proper data payload lgs, err := th.ORM.SelectLogsByBlockRange(testutils.Context(t), 2, 2) require.NoError(t, err) + require.NotZero(t, len(lgs)) assert.Equal(t, hexutil.MustDecode(`0x0000000000000000000000000000000000000000000000000000000000000001`), lgs[0].Data) // Single block reorg and log poller not working for a while, mine blocks and progress with finalization @@ -1208,6 +1208,7 @@ func TestLogPoller_PollAndSaveLogsDeepReorg(t *testing.T) { // Expect L1_2 to be properly updated lgs, err = th.ORM.SelectLogsByBlockRange(testutils.Context(t), 2, 2) require.NoError(t, err) + require.NotZero(t, len(lgs)) assert.Equal(t, hexutil.MustDecode(`0x0000000000000000000000000000000000000000000000000000000000000002`), lgs[0].Data) th.assertHaveCanonical(t, 1, 1) th.assertDontHave(t, 2, 3) // These blocks are backfilled @@ -1301,6 +1302,7 @@ func TestLogPoller_LoadFilters(t *testing.T) { func TestLogPoller_GetBlocks_Range(t *testing.T) { t.Parallel() + lpOpts := logpoller.Opts{ UseFinalityTag: false, FinalityDepth: 2, @@ -1310,7 +1312,15 @@ func TestLogPoller_GetBlocks_Range(t *testing.T) { } th := SetupTH(t, lpOpts) - err := th.LogPoller.RegisterFilter(testutils.Context(t), logpoller.Filter{ + _, err := th.Emitter1.EmitLog1(th.Owner, []*big.Int{big.NewInt(1)}) + require.NoError(t, err) + th.Client.Commit() // Commit block #2 with log in it + + _, err = th.Emitter1.EmitLog1(th.Owner, []*big.Int{big.NewInt(2)}) + require.NoError(t, err) + th.Client.Commit() // Commit block #3 with a different log + + err = th.LogPoller.RegisterFilter(testutils.Context(t), logpoller.Filter{ Name: "GetBlocks Test", EventSigs: []common.Hash{EmitterABI.Events["Log1"].ID, EmitterABI.Events["Log2"].ID}, Addresses: []common.Address{th.EmitterAddress1, th.EmitterAddress2}, @@ -1330,16 +1340,13 @@ func TestLogPoller_GetBlocks_Range(t *testing.T) { assert.Equal(t, 1, len(blocks)) assert.Equal(t, 1, int(blocks[0].BlockNumber)) - // LP fails to retrieve block 2 because it's neither in DB nor returned by RPC + // LP fails to return block 2 because it hasn't been finalized yet blockNums = []uint64{2} _, err = th.LogPoller.GetBlocksRange(testutils.Context(t), blockNums) require.Error(t, err) - assert.Equal(t, "blocks were not found in db or RPC call: [2]", err.Error()) + assert.Equal(t, "Received unfinalized block 2 while expecting finalized block (latestFinalizedBlockNumber = 1)", err.Error()) - // Emit a log and mine block #2 - _, err = th.Emitter1.EmitLog1(th.Owner, []*big.Int{big.NewInt(1)}) - require.NoError(t, err) - th.Client.Commit() + th.Client.Commit() // Commit block #4, so that block #2 is finalized // Assert block 2 is not yet in DB _, err = th.ORM.SelectBlockByNumber(testutils.Context(t), 2) @@ -1351,10 +1358,7 @@ func TestLogPoller_GetBlocks_Range(t *testing.T) { assert.Equal(t, 1, len(rpcBlocks)) assert.Equal(t, 2, int(rpcBlocks[0].BlockNumber)) - // Emit a log and mine block #3 - _, err = th.Emitter1.EmitLog1(th.Owner, []*big.Int{big.NewInt(2)}) - require.NoError(t, err) - th.Client.Commit() + th.Client.Commit() // commit block #5 so that #3 becomes finalized // Assert block 3 is not yet in DB _, err = th.ORM.SelectBlockByNumber(testutils.Context(t), 3) @@ -1368,12 +1372,9 @@ func TestLogPoller_GetBlocks_Range(t *testing.T) { assert.Equal(t, 1, int(rpcBlocks2[0].BlockNumber)) assert.Equal(t, 3, int(rpcBlocks2[1].BlockNumber)) - // after calling PollAndSaveLogs, block 2 & 3 are persisted in DB + // after calling PollAndSaveLogs, block 3 (latest finalized block) is persisted in DB th.LogPoller.PollAndSaveLogs(testutils.Context(t), 1) - block, err := th.ORM.SelectBlockByNumber(testutils.Context(t), 2) - require.NoError(t, err) - assert.Equal(t, 2, int(block.BlockNumber)) - block, err = th.ORM.SelectBlockByNumber(testutils.Context(t), 3) + block, err := th.ORM.SelectBlockByNumber(testutils.Context(t), 3) require.NoError(t, err) assert.Equal(t, 3, int(block.BlockNumber)) @@ -1507,9 +1508,9 @@ func TestLogPoller_DBErrorHandling(t *testing.T) { time.Sleep(100 * time.Millisecond) require.NoError(t, lp.Start(ctx)) - require.Eventually(t, func() bool { + testutils.AssertEventually(t, func() bool { return observedLogs.Len() >= 1 - }, 2*time.Second, 20*time.Millisecond) + }) err = lp.Close() require.NoError(t, err) From 0c4c24ad8c95e505cd2a29be711cc40e612658b0 Mon Sep 17 00:00:00 2001 From: Christopher Dimitri Sastropranoto Date: Fri, 26 Apr 2024 12:44:17 +0700 Subject: [PATCH 23/34] Add function to remove operators in Capability Registry (#12979) * update remove operators function * address PR feedback --- .changeset/smooth-comics-love.md | 5 + contracts/.changeset/hot-weeks-agree.md | 5 + .../src/v0.8/keystone/CapabilityRegistry.sol | 14 ++ ...lityRegistry_RemoveNodeOperatorsTest.t.sol | 46 ++++++ .../keystone_capability_registry.go | 147 +++++++++++++++++- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 6 files changed, 216 insertions(+), 3 deletions(-) create mode 100644 .changeset/smooth-comics-love.md create mode 100644 contracts/.changeset/hot-weeks-agree.md create mode 100644 contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodeOperatorsTest.t.sol diff --git a/.changeset/smooth-comics-love.md b/.changeset/smooth-comics-love.md new file mode 100644 index 00000000000..6d41284978d --- /dev/null +++ b/.changeset/smooth-comics-love.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +update keystone gethwrapper with remove operator function #internal diff --git a/contracts/.changeset/hot-weeks-agree.md b/contracts/.changeset/hot-weeks-agree.md new file mode 100644 index 00000000000..5bd77e9ebe5 --- /dev/null +++ b/contracts/.changeset/hot-weeks-agree.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +add function to remove node operators from capability registry diff --git a/contracts/src/v0.8/keystone/CapabilityRegistry.sol b/contracts/src/v0.8/keystone/CapabilityRegistry.sol index ad452f1606b..faedd858bef 100644 --- a/contracts/src/v0.8/keystone/CapabilityRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilityRegistry.sol @@ -34,6 +34,10 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @param name The human readable name of the node operator event NodeOperatorAdded(uint256 nodeOperatorId, address indexed admin, string name); + /// @notice This event is emitted when a node operator is removed + /// @param nodeOperatorId The ID of the node operator that was removed + event NodeOperatorRemoved(uint256 nodeOperatorId); + /// @notice This event is emitted when a new capability is added /// @param capabilityId The ID of the newly added capability event CapabilityAdded(bytes32 indexed capabilityId); @@ -64,6 +68,16 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { } } + /// @notice Removes a node operator + /// @param nodeOperatorIds The IDs of the node operators to remove + function removeNodeOperators(uint256[] calldata nodeOperatorIds) external onlyOwner { + for (uint256 i; i < nodeOperatorIds.length; ++i) { + uint256 nodeOperatorId = nodeOperatorIds[i]; + delete s_nodeOperators[nodeOperatorId]; + emit NodeOperatorRemoved(nodeOperatorId); + } + } + /// @notice Gets a node operator's data /// @param nodeOperatorId The ID of the node operator to query for /// @return NodeOperator The node operator data diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodeOperatorsTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodeOperatorsTest.t.sol new file mode 100644 index 00000000000..31b043fab3e --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodeOperatorsTest.t.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilityRegistry} from "../CapabilityRegistry.sol"; + +contract CapabilityRegistry_RemoveNodeOperatorsTest is BaseTest { + event NodeOperatorRemoved(uint256 nodeOperatorId); + + uint256 private constant TEST_NODE_OPERATOR_ONE_ID = 0; + uint256 private constant TEST_NODE_OPERATOR_TWO_ID = 1; + + function setUp() public override { + BaseTest.setUp(); + changePrank(ADMIN); + s_capabilityRegistry.addNodeOperators(_getNodeOperators()); + } + + function test_RevertWhen_CalledByNonOwner() public { + changePrank(STRANGER); + vm.expectRevert("Only callable by owner"); + uint256[] memory nodeOperatorsToRemove = new uint256[](2); + nodeOperatorsToRemove[1] = 1; + s_capabilityRegistry.removeNodeOperators(nodeOperatorsToRemove); + } + + function test_RemovesNodeOperator() public { + changePrank(ADMIN); + + vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); + emit NodeOperatorRemoved(TEST_NODE_OPERATOR_ONE_ID); + vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); + emit NodeOperatorRemoved(TEST_NODE_OPERATOR_TWO_ID); + uint256[] memory nodeOperatorsToRemove = new uint256[](2); + nodeOperatorsToRemove[1] = 1; + s_capabilityRegistry.removeNodeOperators(nodeOperatorsToRemove); + + CapabilityRegistry.NodeOperator memory nodeOperatorOne = s_capabilityRegistry.getNodeOperator(0); + assertEq(nodeOperatorOne.admin, address(0)); + assertEq(nodeOperatorOne.name, ""); + + CapabilityRegistry.NodeOperator memory nodeOperatorTwo = s_capabilityRegistry.getNodeOperator(1); + assertEq(nodeOperatorTwo.admin, address(0)); + assertEq(nodeOperatorTwo.name, ""); + } +} diff --git a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go index ef8b252b924..47c65d5276b 100644 --- a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go +++ b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go @@ -41,8 +41,8 @@ type CapabilityRegistryNodeOperator struct { } var CapabilityRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b610d9e806101576000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c80636e5f2869116100765780638da5cb5b1161005b5780638da5cb5b146101885780639cb7c5f4146101b0578063f2fde38b1461021757600080fd5b80636e5f28691461016d57806379ba50971461018057600080fd5b8063181f5a77146100a8578063229111f5146100f0578063398f37731461013857806365c14dc71461014d575b600080fd5b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516100e7919061081d565b60405180910390f35b61012a6100fe366004610837565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b6040519081526020016100e7565b61014b610146366004610859565b61022a565b005b61016061015b3660046108ce565b6103c8565b6040516100e791906108e7565b61014b61017b36600461092a565b6104ae565b61014b61052b565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e7565b6101fc6101be3660046108ce565b604080518082019091526000808252602082015250600090815260026020908152604091829020825180840190935280548352600101549082015290565b604080518251815260209283015192810192909252016100e7565b61014b61022536600461096b565b61062d565b610232610641565b60005b818110156103c357600083838381811061025157610251610986565b905060200281019061026391906109b5565b61026c90610a9a565b805190915073ffffffffffffffffffffffffffffffffffffffff166102bd576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600454604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526003909252939020825181547fffffffffffffffffffffffff0000000000000000000000000000000000000000169216919091178155915190919060018201906103409082610bff565b5090505060046000815461035390610d19565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b916103a891859190610d78565b60405180910390a25050806103bc90610d19565b9050610235565b505050565b6040805180820190915260008152606060208201526000828152600360209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff168352600181018054919284019161042590610b64565b80601f016020809104026020016040519081016040528092919081815260200182805461045190610b64565b801561049e5780601f106104735761010080835404028352916020019161049e565b820191906000526020600020905b81548152906001019060200180831161048157829003601f168201915b5050505050815250509050919050565b6104b6610641565b60408051823560208083018290528085013583850181905284518085038601815260609094018086528451948301949094206000818152600290935294822092835560019092019190915582917f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff069190a25050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146105b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610635610641565b61063e816106c4565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016105a8565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610743576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016105a8565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000815180845260005b818110156107df576020818501810151868301820152016107c3565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061083060208301846107b9565b9392505050565b6000806040838503121561084a57600080fd5b50508035926020909101359150565b6000806020838503121561086c57600080fd5b823567ffffffffffffffff8082111561088457600080fd5b818501915085601f83011261089857600080fd5b8135818111156108a757600080fd5b8660208260051b85010111156108bc57600080fd5b60209290920196919550909350505050565b6000602082840312156108e057600080fd5b5035919050565b6020815273ffffffffffffffffffffffffffffffffffffffff82511660208201526000602083015160408084015261092260608401826107b9565b949350505050565b60006040828403121561093c57600080fd5b50919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461096657600080fd5b919050565b60006020828403121561097d57600080fd5b61083082610942565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126109e957600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610a4557610a456109f3565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610a9257610a926109f3565b604052919050565b600060408236031215610aac57600080fd5b610ab4610a22565b610abd83610942565b815260208084013567ffffffffffffffff80821115610adb57600080fd5b9085019036601f830112610aee57600080fd5b813581811115610b0057610b006109f3565b610b30847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610a4b565b91508082523684828501011115610b4657600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c90821680610b7857607f821691505b60208210810361093c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b601f8211156103c357600081815260208120601f850160051c81016020861015610bd85750805b601f850160051c820191505b81811015610bf757828155600101610be4565b505050505050565b815167ffffffffffffffff811115610c1957610c196109f3565b610c2d81610c278454610b64565b84610bb1565b602080601f831160018114610c805760008415610c4a5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610bf7565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015610ccd57888601518255948401946001909101908401610cae565b5085821015610d0957878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610d71577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b82815260406020820152600061092260408301846107b956fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b610ef1806101576000396000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80636e5f2869116100765780638da5cb5b1161005b5780638da5cb5b146101b65780639cb7c5f4146101de578063f2fde38b1461024557600080fd5b80636e5f28691461019b57806379ba5097146101ae57600080fd5b8063229111f5116100a7578063229111f514610120578063398f37731461016857806365c14dc71461017b57600080fd5b8063181f5a77146100c35780631cdf63431461010b575b600080fd5b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516101029190610957565b60405180910390f35b61011e6101193660046109bd565b610258565b005b61015a61012e3660046109ff565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b604051908152602001610102565b61011e6101763660046109bd565b61031b565b61018e610189366004610a21565b6104b4565b6040516101029190610a3a565b61011e6101a9366004610a7d565b61059a565b61011e610617565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610102565b61022a6101ec366004610a21565b604080518082019091526000808252602082015250600090815260026020908152604091829020825180840190935280548352600101549082015290565b60408051825181526020928301519281019290925201610102565b61011e610253366004610abe565b610719565b61026061072d565b60005b8181101561031657600083838381811061027f5761027f610ad9565b60209081029290920135600081815260039093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506102d060018301826108a5565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a15061030f81610b08565b9050610263565b505050565b61032361072d565b60005b8181101561031657600083838381811061034257610342610ad9565b90506020028101906103549190610b67565b61035d90610c4c565b805190915073ffffffffffffffffffffffffffffffffffffffff166103ae576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600454604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526003909252939020825181547fffffffffffffffffffffffff0000000000000000000000000000000000000000169216919091178155915190919060018201906104319082610db1565b5090505060046000815461044490610b08565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b9161049991859190610ecb565b60405180910390a25050806104ad90610b08565b9050610326565b6040805180820190915260008152606060208201526000828152600360209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff168352600181018054919284019161051190610d16565b80601f016020809104026020016040519081016040528092919081815260200182805461053d90610d16565b801561058a5780601f1061055f5761010080835404028352916020019161058a565b820191906000526020600020905b81548152906001019060200180831161056d57829003601f168201915b5050505050815250509050919050565b6105a261072d565b60408051823560208083018290528085013583850181905284518085038601815260609094018086528451948301949094206000818152600290935294822092835560019092019190915582917f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff069190a25050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461069d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61072161072d565b61072a816107b0565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610694565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361082f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610694565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b5080546108b190610d16565b6000825580601f106108c1575050565b601f01602090049060005260206000209081019061072a91905b808211156108ef57600081556001016108db565b5090565b6000815180845260005b81811015610919576020818501810151868301820152016108fd565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061096a60208301846108f3565b9392505050565b60008083601f84011261098357600080fd5b50813567ffffffffffffffff81111561099b57600080fd5b6020830191508360208260051b85010111156109b657600080fd5b9250929050565b600080602083850312156109d057600080fd5b823567ffffffffffffffff8111156109e757600080fd5b6109f385828601610971565b90969095509350505050565b60008060408385031215610a1257600080fd5b50508035926020909101359150565b600060208284031215610a3357600080fd5b5035919050565b6020815273ffffffffffffffffffffffffffffffffffffffff825116602082015260006020830151604080840152610a7560608401826108f3565b949350505050565b600060408284031215610a8f57600080fd5b50919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610ab957600080fd5b919050565b600060208284031215610ad057600080fd5b61096a82610a95565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610b60577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610b9b57600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610bf757610bf7610ba5565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610c4457610c44610ba5565b604052919050565b600060408236031215610c5e57600080fd5b610c66610bd4565b610c6f83610a95565b815260208084013567ffffffffffffffff80821115610c8d57600080fd5b9085019036601f830112610ca057600080fd5b813581811115610cb257610cb2610ba5565b610ce2847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610bfd565b91508082523684828501011115610cf857600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c90821680610d2a57607f821691505b602082108103610a8f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b601f82111561031657600081815260208120601f850160051c81016020861015610d8a5750805b601f850160051c820191505b81811015610da957828155600101610d96565b505050505050565b815167ffffffffffffffff811115610dcb57610dcb610ba5565b610ddf81610dd98454610d16565b84610d63565b602080601f831160018114610e325760008415610dfc5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610da9565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015610e7f57888601518255948401946001909101908401610e60565b5085821015610ebb57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b828152604060208201526000610a7560408301846108f356fea164736f6c6343000813000a", } var CapabilityRegistryABI = CapabilityRegistryMetaData.ABI @@ -327,6 +327,18 @@ func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddNodeOperators return _CapabilityRegistry.Contract.AddNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperators) } +func (_CapabilityRegistry *CapabilityRegistryTransactor) RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []*big.Int) (*types.Transaction, error) { + return _CapabilityRegistry.contract.Transact(opts, "removeNodeOperators", nodeOperatorIds) +} + +func (_CapabilityRegistry *CapabilityRegistrySession) RemoveNodeOperators(nodeOperatorIds []*big.Int) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.RemoveNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperatorIds) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) RemoveNodeOperators(nodeOperatorIds []*big.Int) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.RemoveNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperatorIds) +} + func (_CapabilityRegistry *CapabilityRegistryTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { return _CapabilityRegistry.contract.Transact(opts, "transferOwnership", to) } @@ -595,6 +607,123 @@ func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeOperatorAdded(lo return event, nil } +type CapabilityRegistryNodeOperatorRemovedIterator struct { + Event *CapabilityRegistryNodeOperatorRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilityRegistryNodeOperatorRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryNodeOperatorRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryNodeOperatorRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilityRegistryNodeOperatorRemovedIterator) Error() error { + return it.fail +} + +func (it *CapabilityRegistryNodeOperatorRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilityRegistryNodeOperatorRemoved struct { + NodeOperatorId *big.Int + Raw types.Log +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterNodeOperatorRemoved(opts *bind.FilterOpts) (*CapabilityRegistryNodeOperatorRemovedIterator, error) { + + logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "NodeOperatorRemoved") + if err != nil { + return nil, err + } + return &CapabilityRegistryNodeOperatorRemovedIterator{contract: _CapabilityRegistry.contract, event: "NodeOperatorRemoved", logs: logs, sub: sub}, nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchNodeOperatorRemoved(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorRemoved) (event.Subscription, error) { + + logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "NodeOperatorRemoved") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilityRegistryNodeOperatorRemoved) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeOperatorRemoved", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeOperatorRemoved(log types.Log) (*CapabilityRegistryNodeOperatorRemoved, error) { + event := new(CapabilityRegistryNodeOperatorRemoved) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeOperatorRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type CapabilityRegistryOwnershipTransferRequestedIterator struct { Event *CapabilityRegistryOwnershipTransferRequested @@ -873,6 +1002,8 @@ func (_CapabilityRegistry *CapabilityRegistry) ParseLog(log types.Log) (generate return _CapabilityRegistry.ParseCapabilityAdded(log) case _CapabilityRegistry.abi.Events["NodeOperatorAdded"].ID: return _CapabilityRegistry.ParseNodeOperatorAdded(log) + case _CapabilityRegistry.abi.Events["NodeOperatorRemoved"].ID: + return _CapabilityRegistry.ParseNodeOperatorRemoved(log) case _CapabilityRegistry.abi.Events["OwnershipTransferRequested"].ID: return _CapabilityRegistry.ParseOwnershipTransferRequested(log) case _CapabilityRegistry.abi.Events["OwnershipTransferred"].ID: @@ -891,6 +1022,10 @@ func (CapabilityRegistryNodeOperatorAdded) Topic() common.Hash { return common.HexToHash("0xda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b") } +func (CapabilityRegistryNodeOperatorRemoved) Topic() common.Hash { + return common.HexToHash("0x1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f") +} + func (CapabilityRegistryOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } @@ -920,6 +1055,8 @@ type CapabilityRegistryInterface interface { AddNodeOperators(opts *bind.TransactOpts, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) + RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []*big.Int) (*types.Transaction, error) + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) FilterCapabilityAdded(opts *bind.FilterOpts, capabilityId [][32]byte) (*CapabilityRegistryCapabilityAddedIterator, error) @@ -934,6 +1071,12 @@ type CapabilityRegistryInterface interface { ParseNodeOperatorAdded(log types.Log) (*CapabilityRegistryNodeOperatorAdded, error) + FilterNodeOperatorRemoved(opts *bind.FilterOpts) (*CapabilityRegistryNodeOperatorRemovedIterator, error) + + WatchNodeOperatorRemoved(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorRemoved) (event.Subscription, error) + + ParseNodeOperatorRemoved(log types.Log) (*CapabilityRegistryNodeOperatorRemoved, error) + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilityRegistryOwnershipTransferRequestedIterator, error) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 836eb3e68b7..62a75a8a644 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,4 @@ GETH_VERSION: 1.13.8 forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin b4c900aae9e022f01abbac7993d41f93912247613ac6270b0c4da4ef6f2016e3 -keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin 579334dfcb59da4221823735dc815116745b488ddde327199367e04457aac808 +keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin 9eaa36e45c1b33c1fa72b7e25d6d1ca351413225611abb84ae053270b569cca4 ocr3_capability: ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin 9dcbdf55bd5729ba266148da3f17733eb592c871c2108ccca546618628fd9ad2 From 8c8994e24284236645509b4c49152e6270ce0e35 Mon Sep 17 00:00:00 2001 From: george-dorin <120329946+george-dorin@users.noreply.github.com> Date: Fri, 26 Apr 2024 15:55:40 +0300 Subject: [PATCH 24/34] Validate config on NewApplication (#12997) * validate config on new application spawn * Add changeset * Check config only in the rebroadcast-transactions command --- .changeset/pink-schools-provide.md | 5 +++++ core/cmd/shell_local.go | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 .changeset/pink-schools-provide.md diff --git a/.changeset/pink-schools-provide.md b/.changeset/pink-schools-provide.md new file mode 100644 index 00000000000..6b2aa5ea0c4 --- /dev/null +++ b/.changeset/pink-schools-provide.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#bugfix Fixed an issue where the `rebroadcast-transactions` commands did not execute config validation. diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go index 6dbffbe404a..24cb43e2090 100644 --- a/core/cmd/shell_local.go +++ b/core/cmd/shell_local.go @@ -580,6 +580,11 @@ func (s *Shell) RebroadcastTransactions(c *cli.Context) (err error) { } } + err = s.Config.Validate() + if err != nil { + return err + } + lggr := logger.Sugared(s.Logger.Named("RebroadcastTransactions")) db, err := pg.OpenUnlockedDB(s.Config.AppID(), s.Config.Database()) if err != nil { From f55d8be495a83c97ac5439672563400e12ec2ee7 Mon Sep 17 00:00:00 2001 From: Sam Date: Fri, 26 Apr 2024 10:10:40 -0400 Subject: [PATCH 25/34] Configurable Mercury transmitter parameters (#12680) * Configurable Mercury transmitter parameters * Changeset * Remove commented code * add tag * Rename --- .changeset/sour-jars-cross.md | 13 ++++++ core/cmd/shell.go | 5 ++- core/config/docs/core.toml | 14 +++++++ core/config/mercury_config.go | 7 ++++ core/config/toml/types.go | 20 ++++++++- core/internal/cltest/cltest.go | 3 +- core/services/chainlink/config_mercury.go | 21 ++++++++++ core/services/chainlink/config_test.go | 8 ++++ core/services/chainlink/relayer_factory.go | 9 ++-- .../testdata/config-empty-effective.toml | 4 ++ .../chainlink/testdata/config-full.toml | 4 ++ .../config-multi-chain-effective.toml | 4 ++ core/services/ocr2/delegate.go | 1 + core/services/relay/evm/evm.go | 25 ++++++----- .../services/relay/evm/mercury/transmitter.go | 27 +++++++----- .../relay/evm/mercury/transmitter_test.go | 42 ++++++++++++------- .../evm/mercury/wsrpc/pb/mercury_wsrpc.pb.go | 1 + .../testdata/config-empty-effective.toml | 4 ++ core/web/resolver/testdata/config-full.toml | 4 ++ .../config-multi-chain-effective.toml | 4 ++ docs/CONFIG.md | 27 ++++++++++++ testdata/scripts/node/validate/default.txtar | 4 ++ .../disk-based-logging-disabled.txtar | 4 ++ .../validate/disk-based-logging-no-dir.txtar | 4 ++ .../node/validate/disk-based-logging.txtar | 4 ++ .../node/validate/invalid-ocr-p2p.txtar | 4 ++ testdata/scripts/node/validate/invalid.txtar | 4 ++ testdata/scripts/node/validate/valid.txtar | 4 ++ testdata/scripts/node/validate/warnings.txtar | 4 ++ 29 files changed, 234 insertions(+), 45 deletions(-) create mode 100644 .changeset/sour-jars-cross.md diff --git a/.changeset/sour-jars-cross.md b/.changeset/sour-jars-cross.md new file mode 100644 index 00000000000..b904e8e3dd0 --- /dev/null +++ b/.changeset/sour-jars-cross.md @@ -0,0 +1,13 @@ +--- +"chainlink": patch +--- + +#added + +Add configurability to mercury transmitter + +```toml +[Mercury.Transmitter] +TransmitQueueMaxSize = 10_000 # Default +TransmitTimeout = "5s" # Default +``` diff --git a/core/cmd/shell.go b/core/cmd/shell.go index 0372148e742..adbb66ce63f 100644 --- a/core/cmd/shell.go +++ b/core/cmd/shell.go @@ -174,8 +174,9 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G } evmFactoryCfg := chainlink.EVMFactoryConfig{ - CSAETHKeystore: keyStore, - ChainOpts: legacyevm.ChainOpts{AppConfig: cfg, MailMon: mailMon, DS: ds}, + CSAETHKeystore: keyStore, + ChainOpts: legacyevm.ChainOpts{AppConfig: cfg, MailMon: mailMon, DS: ds}, + MercuryTransmitter: cfg.Mercury().Transmitter(), } // evm always enabled for backward compatibility // TODO BCF-2510 this needs to change in order to clear the path for EVM extraction diff --git a/core/config/docs/core.toml b/core/config/docs/core.toml index 605f6ced0bc..92d75430daf 100644 --- a/core/config/docs/core.toml +++ b/core/config/docs/core.toml @@ -622,3 +622,17 @@ LatestReportDeadline = "5s" # Default [Mercury.TLS] # CertFile is the path to a PEM file of trusted root certificate authority certificates CertFile = "/path/to/client/certs.pem" # Example + +# Mercury.Transmitter controls settings for the mercury transmitter +[Mercury.Transmitter] +# TransmitQueueMaxSize controls the size of the transmit queue. This is scoped +# per OCR instance. If the queue is full, the transmitter will start dropping +# the oldest messages in order to make space. +# +# This is useful if mercury server goes offline and the nop needs to buffer +# transmissions. +TransmitQueueMaxSize = 10_000 # Default +# TransmitTimeout controls how long the transmitter will wait for a response +# when sending a message to the mercury server, before aborting and considering +# the transmission to be failed. +TransmitTimeout = "5s" # Default diff --git a/core/config/mercury_config.go b/core/config/mercury_config.go index 1210fd282ef..f16fc4661a5 100644 --- a/core/config/mercury_config.go +++ b/core/config/mercury_config.go @@ -3,6 +3,7 @@ package config import ( "time" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/types" ) @@ -16,8 +17,14 @@ type MercuryTLS interface { CertFile() string } +type MercuryTransmitter interface { + TransmitQueueMaxSize() uint32 + TransmitTimeout() commonconfig.Duration +} + type Mercury interface { Credentials(credName string) *types.MercuryCredentials Cache() MercuryCache TLS() MercuryTLS + Transmitter() MercuryTransmitter } diff --git a/core/config/toml/types.go b/core/config/toml/types.go index ed52c21e34e..ba74528b3b6 100644 --- a/core/config/toml/types.go +++ b/core/config/toml/types.go @@ -1312,14 +1312,30 @@ func (m *MercuryTLS) ValidateConfig() (err error) { return } +type MercuryTransmitter struct { + TransmitQueueMaxSize *uint32 + TransmitTimeout *commonconfig.Duration +} + +func (m *MercuryTransmitter) setFrom(f *MercuryTransmitter) { + if v := f.TransmitQueueMaxSize; v != nil { + m.TransmitQueueMaxSize = v + } + if v := f.TransmitTimeout; v != nil { + m.TransmitTimeout = v + } +} + type Mercury struct { - Cache MercuryCache `toml:",omitempty"` - TLS MercuryTLS `toml:",omitempty"` + Cache MercuryCache `toml:",omitempty"` + TLS MercuryTLS `toml:",omitempty"` + Transmitter MercuryTransmitter `toml:",omitempty"` } func (m *Mercury) setFrom(f *Mercury) { m.Cache.setFrom(&f.Cache) m.TLS.setFrom(&f.TLS) + m.Transmitter.setFrom(&f.Transmitter) } func (m *Mercury) ValidateConfig() (err error) { diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index dc7079e44d9..58cedbb96e1 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -369,7 +369,8 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn MailMon: mailMon, DS: ds, }, - CSAETHKeystore: keyStore, + CSAETHKeystore: keyStore, + MercuryTransmitter: cfg.Mercury().Transmitter(), } if cfg.EVMEnabled() { diff --git a/core/services/chainlink/config_mercury.go b/core/services/chainlink/config_mercury.go index 27303a68899..1b64e0bde45 100644 --- a/core/services/chainlink/config_mercury.go +++ b/core/services/chainlink/config_mercury.go @@ -3,6 +3,7 @@ package chainlink import ( "time" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/config" @@ -25,6 +26,8 @@ func (m *mercuryCacheConfig) LatestReportDeadline() time.Duration { return m.c.LatestReportDeadline.Duration() } +var _ config.MercuryTLS = (*mercuryTLSConfig)(nil) + type mercuryTLSConfig struct { c toml.MercuryTLS } @@ -33,6 +36,20 @@ func (m *mercuryTLSConfig) CertFile() string { return *m.c.CertFile } +var _ config.MercuryTransmitter = (*mercuryTransmitterConfig)(nil) + +type mercuryTransmitterConfig struct { + c toml.MercuryTransmitter +} + +func (m *mercuryTransmitterConfig) TransmitQueueMaxSize() uint32 { + return *m.c.TransmitQueueMaxSize +} + +func (m *mercuryTransmitterConfig) TransmitTimeout() commonconfig.Duration { + return *m.c.TransmitTimeout +} + type mercuryConfig struct { c toml.Mercury s toml.MercurySecrets @@ -60,3 +77,7 @@ func (m *mercuryConfig) Cache() config.MercuryCache { func (m *mercuryConfig) TLS() config.MercuryTLS { return &mercuryTLSConfig{c: m.c.TLS} } + +func (m *mercuryConfig) Transmitter() config.MercuryTransmitter { + return &mercuryTransmitterConfig{c: m.c.Transmitter} +} diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index d02948fd07b..0d40697345d 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -710,6 +710,10 @@ func TestConfig_Marshal(t *testing.T) { TLS: toml.MercuryTLS{ CertFile: ptr("/path/to/cert.pem"), }, + Transmitter: toml.MercuryTransmitter{ + TransmitQueueMaxSize: ptr(uint32(123)), + TransmitTimeout: commoncfg.MustNewDuration(234 * time.Second), + }, } for _, tt := range []struct { @@ -1165,6 +1169,10 @@ LatestReportDeadline = '1m42s' [Mercury.TLS] CertFile = '/path/to/cert.pem' + +[Mercury.Transmitter] +TransmitQueueMaxSize = 123 +TransmitTimeout = '3m54s' `}, {"full", full, fullTOML}, {"multi-chain", multiChain, multiChainTOML}, diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index 00db81cce37..31645b7c54d 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -19,6 +19,7 @@ import ( "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" + coreconfig "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" @@ -38,6 +39,7 @@ type RelayerFactory struct { type EVMFactoryConfig struct { legacyevm.ChainOpts evmrelay.CSAETHKeystore + coreconfig.MercuryTransmitter } func (r *RelayerFactory) NewEVM(ctx context.Context, config EVMFactoryConfig) (map[types.RelayID]evmrelay.LoopRelayAdapter, error) { @@ -67,9 +69,10 @@ func (r *RelayerFactory) NewEVM(ctx context.Context, config EVMFactoryConfig) (m } relayerOpts := evmrelay.RelayerOpts{ - DS: ccOpts.DS, - CSAETHKeystore: config.CSAETHKeystore, - MercuryPool: r.MercuryPool, + DS: ccOpts.DS, + CSAETHKeystore: config.CSAETHKeystore, + MercuryPool: r.MercuryPool, + TransmitterConfig: config.MercuryTransmitter, } relayer, err2 := evmrelay.NewRelayer(lggr.Named(relayID.ChainID), chain, relayerOpts) if err2 != nil { diff --git a/core/services/chainlink/testdata/config-empty-effective.toml b/core/services/chainlink/testdata/config-empty-effective.toml index 759a380d15c..38c3ed62017 100644 --- a/core/services/chainlink/testdata/config-empty-effective.toml +++ b/core/services/chainlink/testdata/config-empty-effective.toml @@ -230,6 +230,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index 8a016149e59..b199ae530f5 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -240,6 +240,10 @@ LatestReportDeadline = '1m42s' [Mercury.TLS] CertFile = '/path/to/cert.pem' +[Mercury.Transmitter] +TransmitQueueMaxSize = 123 +TransmitTimeout = '3m54s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 13 diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index a6cba2aaac3..7aa3bb50b35 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -230,6 +230,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index dbde65efe40..4e1eb0cc623 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -198,6 +198,7 @@ type mercuryConfig interface { Credentials(credName string) *types.MercuryCredentials Cache() coreconfig.MercuryCache TLS() coreconfig.MercuryTLS + Transmitter() coreconfig.MercuryTransmitter } type thresholdConfig interface { diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index 9097c217590..737a8e7561e 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -78,7 +78,8 @@ type Relayer struct { codec commontypes.Codec // Mercury - mercuryORM mercury.ORM + mercuryORM mercury.ORM + transmitterCfg mercury.TransmitterConfig // LLO/data streams cdcFactory llo.ChannelDefinitionCacheFactory @@ -93,7 +94,8 @@ type CSAETHKeystore interface { type RelayerOpts struct { DS sqlutil.DataSource CSAETHKeystore - MercuryPool wsrpc.Pool + MercuryPool wsrpc.Pool + TransmitterConfig mercury.TransmitterConfig } func (c RelayerOpts) Validate() error { @@ -122,14 +124,15 @@ func NewRelayer(lggr logger.Logger, chain legacyevm.Chain, opts RelayerOpts) (*R lloORM := llo.NewORM(opts.DS, chain.ID()) cdcFactory := llo.NewChannelDefinitionCacheFactory(lggr, lloORM, chain.LogPoller()) return &Relayer{ - ds: opts.DS, - chain: chain, - lggr: lggr, - ks: opts.CSAETHKeystore, - mercuryPool: opts.MercuryPool, - cdcFactory: cdcFactory, - lloORM: lloORM, - mercuryORM: mercuryORM, + ds: opts.DS, + chain: chain, + lggr: lggr, + ks: opts.CSAETHKeystore, + mercuryPool: opts.MercuryPool, + cdcFactory: cdcFactory, + lloORM: lloORM, + mercuryORM: mercuryORM, + transmitterCfg: opts.TransmitterConfig, }, nil } @@ -246,7 +249,7 @@ func (r *Relayer) NewMercuryProvider(rargs commontypes.RelayArgs, pargs commonty default: return nil, fmt.Errorf("invalid feed version %d", feedID.Version()) } - transmitter := mercury.NewTransmitter(lggr, clients, privKey.PublicKey, rargs.JobID, *relayConfig.FeedID, r.mercuryORM, transmitterCodec) + transmitter := mercury.NewTransmitter(lggr, r.transmitterCfg, clients, privKey.PublicKey, rargs.JobID, *relayConfig.FeedID, r.mercuryORM, transmitterCodec) return NewMercuryProvider(cp, r.chainReader, r.codec, NewMercuryChainReader(r.chain.HeadTracker()), transmitter, reportCodecV1, reportCodecV2, reportCodecV3, lggr), nil } diff --git a/core/services/relay/evm/mercury/transmitter.go b/core/services/relay/evm/mercury/transmitter.go index 6f49ca91bfc..82a76450e5f 100644 --- a/core/services/relay/evm/mercury/transmitter.go +++ b/core/services/relay/evm/mercury/transmitter.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/types/mercury" @@ -33,12 +34,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/utils" ) -var ( - maxTransmitQueueSize = 10_000 - maxDeleteQueueSize = 10_000 - transmitTimeout = 5 * time.Second -) - const ( // Mercury server error codes DuplicateReport = 2 @@ -104,9 +99,15 @@ type TransmitterReportDecoder interface { var _ Transmitter = (*mercuryTransmitter)(nil) +type TransmitterConfig interface { + TransmitQueueMaxSize() uint32 + TransmitTimeout() commonconfig.Duration +} + type mercuryTransmitter struct { services.StateMachine lggr logger.Logger + cfg TransmitterConfig servers map[string]*server @@ -142,6 +143,8 @@ func getPayloadTypes() abi.Arguments { type server struct { lggr logger.Logger + transmitTimeout time.Duration + c wsrpc.Client pm *PersistenceManager q *TransmitQueue @@ -221,7 +224,7 @@ func (s *server) runQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup, feed // queue was closed return } - ctx, cancel := context.WithTimeout(runloopCtx, utils.WithJitter(transmitTimeout)) + ctx, cancel := context.WithTimeout(runloopCtx, utils.WithJitter(s.transmitTimeout)) res, err := s.c.Transmit(ctx, t.Req) cancel() if runloopCtx.Err() != nil { @@ -272,18 +275,19 @@ func (s *server) runQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup, feed } } -func NewTransmitter(lggr logger.Logger, clients map[string]wsrpc.Client, fromAccount ed25519.PublicKey, jobID int32, feedID [32]byte, orm ORM, codec TransmitterReportDecoder) *mercuryTransmitter { +func NewTransmitter(lggr logger.Logger, cfg TransmitterConfig, clients map[string]wsrpc.Client, fromAccount ed25519.PublicKey, jobID int32, feedID [32]byte, orm ORM, codec TransmitterReportDecoder) *mercuryTransmitter { feedIDHex := fmt.Sprintf("0x%x", feedID[:]) servers := make(map[string]*server, len(clients)) for serverURL, client := range clients { cLggr := lggr.Named(serverURL).With("serverURL", serverURL) - pm := NewPersistenceManager(cLggr, serverURL, orm, jobID, maxTransmitQueueSize, flushDeletesFrequency, pruneFrequency) + pm := NewPersistenceManager(cLggr, serverURL, orm, jobID, int(cfg.TransmitQueueMaxSize()), flushDeletesFrequency, pruneFrequency) servers[serverURL] = &server{ cLggr, + cfg.TransmitTimeout().Duration(), client, pm, - NewTransmitQueue(cLggr, serverURL, feedIDHex, maxTransmitQueueSize, pm), - make(chan *pb.TransmitRequest, maxDeleteQueueSize), + NewTransmitQueue(cLggr, serverURL, feedIDHex, int(cfg.TransmitQueueMaxSize()), pm), + make(chan *pb.TransmitRequest, int(cfg.TransmitQueueMaxSize())), transmitSuccessCount.WithLabelValues(feedIDHex, serverURL), transmitDuplicateCount.WithLabelValues(feedIDHex, serverURL), transmitConnectionErrorCount.WithLabelValues(feedIDHex, serverURL), @@ -295,6 +299,7 @@ func NewTransmitter(lggr logger.Logger, clients map[string]wsrpc.Client, fromAcc return &mercuryTransmitter{ services.StateMachine{}, lggr.Named("MercuryTransmitter").With("feedID", feedIDHex), + cfg, servers, codec, feedID, diff --git a/core/services/relay/evm/mercury/transmitter_test.go b/core/services/relay/evm/mercury/transmitter_test.go index 46bf116ed3a..b0da9bea635 100644 --- a/core/services/relay/evm/mercury/transmitter_test.go +++ b/core/services/relay/evm/mercury/transmitter_test.go @@ -4,6 +4,7 @@ import ( "context" "math/big" "testing" + "time" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/pkg/errors" @@ -12,6 +13,7 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -21,6 +23,16 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb" ) +type mockCfg struct{} + +func (m mockCfg) TransmitQueueMaxSize() uint32 { + return 10_000 +} + +func (m mockCfg) TransmitTimeout() commonconfig.Duration { + return *commonconfig.MustNewDuration(1 * time.Hour) +} + func Test_MercuryTransmitter_Transmit(t *testing.T) { lggr := logger.TestLogger(t) db := pgtest.NewSqlxDB(t) @@ -36,7 +48,7 @@ func Test_MercuryTransmitter_Transmit(t *testing.T) { report := sampleV1Report c := &mocks.MockWSRPCClient{} clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) // init the queue since we skipped starting transmitter mt.servers[sURL].q.Init([]*Transmission{}) err := mt.Transmit(testutils.Context(t), sampleReportContext, report, sampleSigs) @@ -50,7 +62,7 @@ func Test_MercuryTransmitter_Transmit(t *testing.T) { report := sampleV2Report c := &mocks.MockWSRPCClient{} clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) // init the queue since we skipped starting transmitter mt.servers[sURL].q.Init([]*Transmission{}) err := mt.Transmit(testutils.Context(t), sampleReportContext, report, sampleSigs) @@ -64,7 +76,7 @@ func Test_MercuryTransmitter_Transmit(t *testing.T) { report := sampleV3Report c := &mocks.MockWSRPCClient{} clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) // init the queue since we skipped starting transmitter mt.servers[sURL].q.Init([]*Transmission{}) err := mt.Transmit(testutils.Context(t), sampleReportContext, report, sampleSigs) @@ -83,7 +95,7 @@ func Test_MercuryTransmitter_Transmit(t *testing.T) { clients[sURL2] = c clients[sURL3] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) // init the queue since we skipped starting transmitter mt.servers[sURL].q.Init([]*Transmission{}) mt.servers[sURL2].q.Init([]*Transmission{}) @@ -125,7 +137,7 @@ func Test_MercuryTransmitter_LatestTimestamp(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) ts, err := mt.LatestTimestamp(testutils.Context(t)) require.NoError(t, err) @@ -141,7 +153,7 @@ func Test_MercuryTransmitter_LatestTimestamp(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) ts, err := mt.LatestTimestamp(testutils.Context(t)) require.NoError(t, err) @@ -155,7 +167,7 @@ func Test_MercuryTransmitter_LatestTimestamp(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) _, err := mt.LatestTimestamp(testutils.Context(t)) require.Error(t, err) assert.Contains(t, err.Error(), "something exploded") @@ -185,7 +197,7 @@ func Test_MercuryTransmitter_LatestTimestamp(t *testing.T) { return out, nil }, } - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) ts, err := mt.LatestTimestamp(testutils.Context(t)) require.NoError(t, err) @@ -228,7 +240,7 @@ func Test_MercuryTransmitter_LatestPrice(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) t.Run("BenchmarkPriceFromReport succeeds", func(t *testing.T) { codec.val = originalPrice @@ -259,7 +271,7 @@ func Test_MercuryTransmitter_LatestPrice(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) price, err := mt.LatestPrice(testutils.Context(t), sampleFeedID) require.NoError(t, err) @@ -273,7 +285,7 @@ func Test_MercuryTransmitter_LatestPrice(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) _, err := mt.LatestPrice(testutils.Context(t), sampleFeedID) require.Error(t, err) assert.Contains(t, err.Error(), "something exploded") @@ -303,7 +315,7 @@ func Test_MercuryTransmitter_FetchInitialMaxFinalizedBlockNumber(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) bn, err := mt.FetchInitialMaxFinalizedBlockNumber(testutils.Context(t)) require.NoError(t, err) @@ -319,7 +331,7 @@ func Test_MercuryTransmitter_FetchInitialMaxFinalizedBlockNumber(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) bn, err := mt.FetchInitialMaxFinalizedBlockNumber(testutils.Context(t)) require.NoError(t, err) @@ -332,7 +344,7 @@ func Test_MercuryTransmitter_FetchInitialMaxFinalizedBlockNumber(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) _, err := mt.FetchInitialMaxFinalizedBlockNumber(testutils.Context(t)) require.Error(t, err) assert.Contains(t, err.Error(), "something exploded") @@ -350,7 +362,7 @@ func Test_MercuryTransmitter_FetchInitialMaxFinalizedBlockNumber(t *testing.T) { }, } clients[sURL] = c - mt := NewTransmitter(lggr, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) + mt := NewTransmitter(lggr, mockCfg{}, clients, sampleClientPubKey, jobID, sampleFeedID, orm, codec) _, err := mt.FetchInitialMaxFinalizedBlockNumber(testutils.Context(t)) require.Error(t, err) assert.Contains(t, err.Error(), "latestReport failed; mismatched feed IDs, expected: 0x1c916b4aa7e57ca7b68ae1bf45653f56b656fd3aa335ef7fae696b663f1b8472, got: 0x") diff --git a/core/services/relay/evm/mercury/wsrpc/pb/mercury_wsrpc.pb.go b/core/services/relay/evm/mercury/wsrpc/pb/mercury_wsrpc.pb.go index 4d05db4380f..0c31a1d7ac9 100644 --- a/core/services/relay/evm/mercury/wsrpc/pb/mercury_wsrpc.pb.go +++ b/core/services/relay/evm/mercury/wsrpc/pb/mercury_wsrpc.pb.go @@ -11,6 +11,7 @@ import ( ) // MercuryClient is the client API for Mercury service. +// type MercuryClient interface { Transmit(ctx context.Context, in *TransmitRequest) (*TransmitResponse, error) LatestReport(ctx context.Context, in *LatestReportRequest) (*LatestReportResponse, error) diff --git a/core/web/resolver/testdata/config-empty-effective.toml b/core/web/resolver/testdata/config-empty-effective.toml index 759a380d15c..38c3ed62017 100644 --- a/core/web/resolver/testdata/config-empty-effective.toml +++ b/core/web/resolver/testdata/config-empty-effective.toml @@ -230,6 +230,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index 69d56974130..75fad4d2fc9 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -240,6 +240,10 @@ LatestReportDeadline = '1m42s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 123 +TransmitTimeout = '3m54s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 13 diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index a6cba2aaac3..7aa3bb50b35 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -230,6 +230,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 0596fcdd84d..f93d990413f 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -1698,6 +1698,33 @@ CertFile = "/path/to/client/certs.pem" # Example ``` CertFile is the path to a PEM file of trusted root certificate authority certificates +## Mercury.Transmitter +```toml +[Mercury.Transmitter] +TransmitQueueMaxSize = 10_000 # Default +TransmitTimeout = "5s" # Default +``` +Mercury.Transmitter controls settings for the mercury transmitter + +### TransmitQueueMaxSize +```toml +TransmitQueueMaxSize = 10_000 # Default +``` +TransmitQueueMaxSize controls the size of the transmit queue. This is scoped +per OCR instance. If the queue is full, the transmitter will start dropping +the oldest messages in order to make space. + +This is useful if mercury server goes offline and the nop needs to buffer +transmissions. + +### TransmitTimeout +```toml +TransmitTimeout = "5s" # Default +``` +TransmitTimeout controls how long the transmitter will wait for a response +when sending a message to the mercury server, before aborting and considering +the transmission to be failed. + ## EVM EVM defaults depend on ChainID: diff --git a/testdata/scripts/node/validate/default.txtar b/testdata/scripts/node/validate/default.txtar index dd3af5f91b6..a8e8e41750d 100644 --- a/testdata/scripts/node/validate/default.txtar +++ b/testdata/scripts/node/validate/default.txtar @@ -242,6 +242,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index 15a476460da..feaf546f022 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -286,6 +286,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar index cc8b4577bfb..b37fed41150 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -286,6 +286,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index c578d200923..6ae02ab38f4 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -286,6 +286,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar index 91ae520532d..45c97477bd5 100644 --- a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar +++ b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar @@ -271,6 +271,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index a5e4b766b6e..df0118bbbbf 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -276,6 +276,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index c220d7f2e5f..edb07fd5e4f 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -283,6 +283,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 diff --git a/testdata/scripts/node/validate/warnings.txtar b/testdata/scripts/node/validate/warnings.txtar index 018aaf95f4c..cf121e959e1 100644 --- a/testdata/scripts/node/validate/warnings.txtar +++ b/testdata/scripts/node/validate/warnings.txtar @@ -265,6 +265,10 @@ LatestReportDeadline = '5s' [Mercury.TLS] CertFile = '' +[Mercury.Transmitter] +TransmitQueueMaxSize = 10000 +TransmitTimeout = '5s' + [Capabilities] [Capabilities.Peering] IncomingMessageBufferSize = 10 From 27d941328655e0cde608c1eff47de736c11e2e58 Mon Sep 17 00:00:00 2001 From: Dmytro Haidashenko <34754799+dhaidashenko@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:28:55 +0200 Subject: [PATCH 26/34] LogPoller CLI command to resolve reorg greater than finality depth (#12867) * find lca and remove block after CLI * fix sort.Find typo * make RemoveBlocks local cmd * tests * added changeset * added tags to the changeset * fixed tests * make cmds, vars cases consistent --- .changeset/brave-dots-breathe.md | 7 ++ core/chains/evm/logpoller/disabled.go | 8 ++ core/chains/evm/logpoller/log_poller.go | 99 +++++++++++++++ core/chains/evm/logpoller/log_poller_test.go | 116 ++++++++++++++++++ core/chains/evm/logpoller/mocks/log_poller.go | 48 ++++++++ core/chains/evm/logpoller/observability.go | 6 + core/chains/evm/logpoller/orm.go | 9 ++ core/chains/evm/logpoller/orm_test.go | 30 +++++ core/cmd/blocks_commands.go | 58 +++++++++ core/cmd/blocks_commands_test.go | 25 ++++ core/cmd/shell_local.go | 79 ++++++++++++ core/cmd/shell_local_test.go | 56 +++++++++ core/internal/mocks/application.go | 50 ++++++++ core/services/chainlink/application.go | 43 +++++++ core/web/api.go | 2 +- core/web/lca_controller.go | 74 +++++++++++ core/web/lca_controller_test.go | 29 +++++ core/web/router.go | 2 + testdata/scripts/blocks/help.txtar | 3 +- testdata/scripts/help-all/help-all.txtar | 2 + testdata/scripts/node/help.txtar | 1 + 21 files changed, 745 insertions(+), 2 deletions(-) create mode 100644 .changeset/brave-dots-breathe.md create mode 100644 core/web/lca_controller.go create mode 100644 core/web/lca_controller_test.go diff --git a/.changeset/brave-dots-breathe.md b/.changeset/brave-dots-breathe.md new file mode 100644 index 00000000000..f1ae4f4d21e --- /dev/null +++ b/.changeset/brave-dots-breathe.md @@ -0,0 +1,7 @@ +--- +"chainlink": minor +--- + +Added a new CLI command, `blocks find-lca,` which finds the latest block that is available in both the database and on the chain for the specified chain. +Added a new CLI command, `node remove-blocks,` which removes all blocks and logs greater than or equal to the specified block number. +#nops #added diff --git a/core/chains/evm/logpoller/disabled.go b/core/chains/evm/logpoller/disabled.go index f3e64378384..6f95b9c55da 100644 --- a/core/chains/evm/logpoller/disabled.go +++ b/core/chains/evm/logpoller/disabled.go @@ -114,3 +114,11 @@ func (d disabled) LatestBlockByEventSigsAddrsWithConfs(ctx context.Context, from func (d disabled) LogsDataWordBetween(ctx context.Context, eventSig common.Hash, address common.Address, wordIndexMin, wordIndexMax int, wordValue common.Hash, confs Confirmations) ([]Log, error) { return nil, ErrDisabled } + +func (d disabled) FindLCA(ctx context.Context) (*LogPollerBlock, error) { + return nil, ErrDisabled +} + +func (d disabled) DeleteLogsAndBlocksAfter(ctx context.Context, start int64) error { + return ErrDisabled +} diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go index 7592ec104c4..cd26889627f 100644 --- a/core/chains/evm/logpoller/log_poller.go +++ b/core/chains/evm/logpoller/log_poller.go @@ -44,6 +44,8 @@ type LogPoller interface { GetFilters() map[string]Filter LatestBlock(ctx context.Context) (LogPollerBlock, error) GetBlocksRange(ctx context.Context, numbers []uint64) ([]LogPollerBlock, error) + FindLCA(ctx context.Context) (*LogPollerBlock, error) + DeleteLogsAndBlocksAfter(ctx context.Context, start int64) error // General querying Logs(ctx context.Context, start, end int64, eventSig common.Hash, address common.Address) ([]Log, error) @@ -1422,6 +1424,103 @@ func (lp *logPoller) IndexedLogsWithSigsExcluding(ctx context.Context, address c return lp.orm.SelectIndexedLogsWithSigsExcluding(ctx, eventSigA, eventSigB, topicIndex, address, fromBlock, toBlock, confs) } +// DeleteLogsAndBlocksAfter - removes blocks and logs starting from the specified block +func (lp *logPoller) DeleteLogsAndBlocksAfter(ctx context.Context, start int64) error { + return lp.orm.DeleteLogsAndBlocksAfter(ctx, start) +} + +func (lp *logPoller) FindLCA(ctx context.Context) (*LogPollerBlock, error) { + latest, err := lp.orm.SelectLatestBlock(ctx) + if err != nil { + return nil, fmt.Errorf("failed to select the latest block: %w", err) + } + + oldest, err := lp.orm.SelectOldestBlock(ctx, 0) + if err != nil { + return nil, fmt.Errorf("failed to select the oldest block: %w", err) + } + + if latest == nil || oldest == nil { + return nil, fmt.Errorf("expected at least one block to be present in DB") + } + + lp.lggr.Debugf("Received request to find LCA. Searching in range [%d, %d]", oldest.BlockNumber, latest.BlockNumber) + + // Find the largest block number for which block hash stored in the DB matches one that we get from the RPC. + // `sort.Find` expects slice of following format s = [1, 0, -1] and returns smallest index i for which s[i] = 0. + // To utilise `sort.Find` we represent range of blocks as slice [latestBlock, latestBlock-1, ..., olderBlock+1, oldestBlock] + // and return 1 if DB block was reorged or 0 if it's still present on chain. + lcaI, found := sort.Find(int(latest.BlockNumber-oldest.BlockNumber)+1, func(i int) int { + const notFound = 1 + const found = 0 + // if there is an error - stop the search + if err != nil { + return notFound + } + + // canceled search + if ctx.Err() != nil { + err = fmt.Errorf("aborted, FindLCA request cancelled: %w", ctx.Err()) + return notFound + } + iBlockNumber := latest.BlockNumber - int64(i) + var dbBlock *LogPollerBlock + // Block with specified block number might not exist in the database, to address that we check closest child + // of the iBlockNumber. If the child is present on chain, it's safe to assume that iBlockNumber is present too + dbBlock, err = lp.orm.SelectOldestBlock(ctx, iBlockNumber) + if err != nil { + err = fmt.Errorf("failed to select block %d by number: %w", iBlockNumber, err) + return notFound + } + + if dbBlock == nil { + err = fmt.Errorf("expected block to exist with blockNumber >= %d as observed block with number %d", iBlockNumber, latest.BlockNumber) + return notFound + } + + lp.lggr.Debugf("Looking for matching block on chain blockNumber: %d blockHash: %s", + dbBlock.BlockNumber, dbBlock.BlockHash) + var chainBlock *evmtypes.Head + chainBlock, err = lp.ec.HeadByHash(ctx, dbBlock.BlockHash) + // our block in DB does not exist on chain + if (chainBlock == nil && err == nil) || errors.Is(err, ethereum.NotFound) { + err = nil + return notFound + } + if err != nil { + err = fmt.Errorf("failed to get block %s from RPC: %w", dbBlock.BlockHash, err) + return notFound + } + + if chainBlock.BlockNumber() != dbBlock.BlockNumber { + err = fmt.Errorf("expected block numbers to match (db: %d, chain: %d), if block hashes match "+ + "(db: %s, chain: %s)", dbBlock.BlockNumber, chainBlock.BlockNumber(), dbBlock.BlockHash, chainBlock.Hash) + return notFound + } + + return found + }) + if err != nil { + return nil, fmt.Errorf("failed to find: %w", err) + } + + if !found { + return nil, fmt.Errorf("failed to find LCA, this means that whole database LogPoller state was reorged out of chain or RPC/Core node is misconfigured") + } + + lcaBlockNumber := latest.BlockNumber - int64(lcaI) + lca, err := lp.orm.SelectBlockByNumber(ctx, lcaBlockNumber) + if err != nil { + return nil, fmt.Errorf("failed to select lca from db: %w", err) + } + + if lca == nil { + return nil, fmt.Errorf("expected lca (blockNum: %d) to exist in DB", lcaBlockNumber) + } + + return lca, nil +} + func EvmWord(i uint64) common.Hash { var b = make([]byte, 8) binary.BigEndian.PutUint64(b, i) diff --git a/core/chains/evm/logpoller/log_poller_test.go b/core/chains/evm/logpoller/log_poller_test.go index 74ec41fa85a..cb211043a4c 100644 --- a/core/chains/evm/logpoller/log_poller_test.go +++ b/core/chains/evm/logpoller/log_poller_test.go @@ -1921,3 +1921,119 @@ func markBlockAsFinalizedByHash(t *testing.T, th TestHarness, blockHash common.H require.NoError(t, err) th.Client.Blockchain().SetFinalized(b.Header()) } + +func TestFindLCA(t *testing.T) { + ctx := testutils.Context(t) + ec := evmtest.NewEthClientMockWithDefaultChain(t) + lggr := logger.Test(t) + chainID := testutils.NewRandomEVMChainID() + db := pgtest.NewSqlxDB(t) + + orm := logpoller.NewORM(chainID, db, lggr) + + lpOpts := logpoller.Opts{ + PollPeriod: time.Hour, + FinalityDepth: 2, + BackfillBatchSize: 20, + RpcBatchSize: 10, + KeepFinalizedBlocksDepth: 1000, + } + + lp := logpoller.NewLogPoller(orm, ec, lggr, lpOpts) + t.Run("Fails, if failed to select oldest block", func(t *testing.T) { + _, err := lp.FindLCA(ctx) + require.ErrorContains(t, err, "failed to select the latest block") + }) + // oldest + require.NoError(t, orm.InsertBlock(ctx, common.HexToHash("0x123"), 10, time.Now(), 0)) + // latest + latestBlockHash := common.HexToHash("0x124") + require.NoError(t, orm.InsertBlock(ctx, latestBlockHash, 16, time.Now(), 0)) + t.Run("Fails, if caller's context canceled", func(t *testing.T) { + lCtx, cancel := context.WithCancel(ctx) + ec.On("HeadByHash", mock.Anything, latestBlockHash).Return(nil, nil).Run(func(_ mock.Arguments) { + cancel() + }).Once() + _, err := lp.FindLCA(lCtx) + require.ErrorContains(t, err, "aborted, FindLCA request cancelled") + + }) + t.Run("Fails, if RPC returns an error", func(t *testing.T) { + expectedError := fmt.Errorf("failed to call RPC") + ec.On("HeadByHash", mock.Anything, latestBlockHash).Return(nil, expectedError).Once() + _, err := lp.FindLCA(ctx) + require.ErrorContains(t, err, expectedError.Error()) + }) + t.Run("Fails, if block numbers do not match", func(t *testing.T) { + ec.On("HeadByHash", mock.Anything, latestBlockHash).Return(&evmtypes.Head{ + Number: 123, + }, nil).Once() + _, err := lp.FindLCA(ctx) + require.ErrorContains(t, err, "expected block numbers to match") + }) + t.Run("Fails, if none of the blocks in db matches on chain", func(t *testing.T) { + ec.On("HeadByHash", mock.Anything, mock.Anything).Return(nil, nil).Times(3) + _, err := lp.FindLCA(ctx) + require.ErrorContains(t, err, "failed to find LCA, this means that whole database LogPoller state was reorged out of chain or RPC/Core node is misconfigured") + }) + + type block struct { + BN int + Exists bool + } + testCases := []struct { + Name string + Blocks []block + ExpectedBlockNumber int + ExpectedError error + }{ + { + Name: "All of the blocks are present on chain - returns the latest", + Blocks: []block{{BN: 1, Exists: true}, {BN: 2, Exists: true}, {BN: 3, Exists: true}, {BN: 4, Exists: true}}, + ExpectedBlockNumber: 4, + }, + { + Name: "None of the blocks exists on chain - returns an erro", + Blocks: []block{{BN: 1, Exists: false}, {BN: 2, Exists: false}, {BN: 3, Exists: false}, {BN: 4, Exists: false}}, + ExpectedBlockNumber: 0, + ExpectedError: fmt.Errorf("failed to find LCA, this means that whole database LogPoller state was reorged out of chain or RPC/Core node is misconfigured"), + }, + { + Name: "Only latest block does not exist", + Blocks: []block{{BN: 1, Exists: true}, {BN: 2, Exists: true}, {BN: 3, Exists: true}, {BN: 4, Exists: false}}, + ExpectedBlockNumber: 3, + }, + { + Name: "Only oldest block exists on chain", + Blocks: []block{{BN: 1, Exists: true}, {BN: 2, Exists: false}, {BN: 3, Exists: false}, {BN: 4, Exists: false}}, + ExpectedBlockNumber: 1, + }, + } + + blockHashI := int64(0) + for _, tc := range testCases { + t.Run(tc.Name, func(t *testing.T) { + // reset the database + require.NoError(t, orm.DeleteLogsAndBlocksAfter(ctx, 0)) + for _, b := range tc.Blocks { + blockHashI++ + hash := common.BigToHash(big.NewInt(blockHashI)) + require.NoError(t, orm.InsertBlock(ctx, hash, int64(b.BN), time.Now(), 0)) + // Hashes are unique for all test cases + var onChainBlock *evmtypes.Head + if b.Exists { + onChainBlock = &evmtypes.Head{Number: int64(b.BN)} + } + ec.On("HeadByHash", mock.Anything, hash).Return(onChainBlock, nil).Maybe() + } + + result, err := lp.FindLCA(ctx) + if tc.ExpectedError != nil { + require.ErrorContains(t, err, tc.ExpectedError.Error()) + } else { + require.NotNil(t, result) + require.Equal(t, result.BlockNumber, int64(tc.ExpectedBlockNumber), "expected block numbers to match") + } + }) + } +} diff --git a/core/chains/evm/logpoller/mocks/log_poller.go b/core/chains/evm/logpoller/mocks/log_poller.go index 548e9ca3b90..ef3f4dbd428 100644 --- a/core/chains/evm/logpoller/mocks/log_poller.go +++ b/core/chains/evm/logpoller/mocks/log_poller.go @@ -37,6 +37,54 @@ func (_m *LogPoller) Close() error { return r0 } +// DeleteLogsAndBlocksAfter provides a mock function with given fields: ctx, start +func (_m *LogPoller) DeleteLogsAndBlocksAfter(ctx context.Context, start int64) error { + ret := _m.Called(ctx, start) + + if len(ret) == 0 { + panic("no return value specified for DeleteLogsAndBlocksAfter") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok { + r0 = rf(ctx, start) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// FindLCA provides a mock function with given fields: ctx +func (_m *LogPoller) FindLCA(ctx context.Context) (*logpoller.LogPollerBlock, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for FindLCA") + } + + var r0 *logpoller.LogPollerBlock + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*logpoller.LogPollerBlock, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *logpoller.LogPollerBlock); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*logpoller.LogPollerBlock) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetBlocksRange provides a mock function with given fields: ctx, numbers func (_m *LogPoller) GetBlocksRange(ctx context.Context, numbers []uint64) ([]logpoller.LogPollerBlock, error) { ret := _m.Called(ctx, numbers) diff --git a/core/chains/evm/logpoller/observability.go b/core/chains/evm/logpoller/observability.go index 14dec5274ad..8f3cdfe185e 100644 --- a/core/chains/evm/logpoller/observability.go +++ b/core/chains/evm/logpoller/observability.go @@ -151,6 +151,12 @@ func (o *ObservedORM) SelectLatestBlock(ctx context.Context) (*LogPollerBlock, e }) } +func (o *ObservedORM) SelectOldestBlock(ctx context.Context, minAllowedBlockNumber int64) (*LogPollerBlock, error) { + return withObservedQuery(o, "SelectOldestBlock", func() (*LogPollerBlock, error) { + return o.ORM.SelectOldestBlock(ctx, minAllowedBlockNumber) + }) +} + func (o *ObservedORM) SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs Confirmations) (*Log, error) { return withObservedQuery(o, "SelectLatestLogByEventSigWithConfs", func() (*Log, error) { return o.ORM.SelectLatestLogByEventSigWithConfs(ctx, eventSig, address, confs) diff --git a/core/chains/evm/logpoller/orm.go b/core/chains/evm/logpoller/orm.go index 838a38c8ebb..5e0a74a9183 100644 --- a/core/chains/evm/logpoller/orm.go +++ b/core/chains/evm/logpoller/orm.go @@ -38,6 +38,7 @@ type ORM interface { SelectBlockByNumber(ctx context.Context, blockNumber int64) (*LogPollerBlock, error) SelectBlockByHash(ctx context.Context, hash common.Hash) (*LogPollerBlock, error) SelectLatestBlock(ctx context.Context) (*LogPollerBlock, error) + SelectOldestBlock(ctx context.Context, minAllowedBlockNumber int64) (*LogPollerBlock, error) SelectLogs(ctx context.Context, start, end int64, address common.Address, eventSig common.Hash) ([]Log, error) SelectLogsWithSigs(ctx context.Context, start, end int64, address common.Address, eventSigs []common.Hash) ([]Log, error) @@ -202,6 +203,14 @@ func (o *DSORM) SelectLatestBlock(ctx context.Context) (*LogPollerBlock, error) return &b, nil } +func (o *DSORM) SelectOldestBlock(ctx context.Context, minAllowedBlockNumber int64) (*LogPollerBlock, error) { + var b LogPollerBlock + if err := o.ds.GetContext(ctx, &b, `SELECT * FROM evm.log_poller_blocks WHERE evm_chain_id = $1 AND block_number >= $2 ORDER BY block_number ASC LIMIT 1`, ubig.New(o.chainID), minAllowedBlockNumber); err != nil { + return nil, err + } + return &b, nil +} + func (o *DSORM) SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig common.Hash, address common.Address, confs Confirmations) (*Log, error) { args, err := newQueryArgsForEvent(o.chainID, address, eventSig). withConfs(confs). diff --git a/core/chains/evm/logpoller/orm_test.go b/core/chains/evm/logpoller/orm_test.go index 8a45ff2f1c5..2a1be62dd5b 100644 --- a/core/chains/evm/logpoller/orm_test.go +++ b/core/chains/evm/logpoller/orm_test.go @@ -1759,3 +1759,33 @@ func Benchmark_DeleteExpiredLogs(b *testing.B) { assert.NoError(b, err1) } } + +func TestSelectOldestBlock(t *testing.T) { + th := SetupTH(t, lpOpts) + o1 := th.ORM + o2 := th.ORM2 + ctx := testutils.Context(t) + t.Run("Selects oldest within given chain", func(t *testing.T) { + // insert blocks + require.NoError(t, o2.InsertBlock(ctx, common.HexToHash("0x1231"), 11, time.Now(), 0)) + require.NoError(t, o2.InsertBlock(ctx, common.HexToHash("0x1232"), 12, time.Now(), 0)) + // insert newer block from different chain + require.NoError(t, o1.InsertBlock(ctx, common.HexToHash("0x1233"), 13, time.Now(), 0)) + require.NoError(t, o1.InsertBlock(ctx, common.HexToHash("0x1231"), 14, time.Now(), 0)) + block, err := o1.SelectOldestBlock(ctx, 0) + require.NoError(t, err) + require.NotNil(t, block) + require.Equal(t, block.BlockNumber, int64(13)) + require.Equal(t, block.BlockHash, common.HexToHash("0x1233")) + }) + t.Run("Does not select blocks older than specified limit", func(t *testing.T) { + require.NoError(t, o1.InsertBlock(ctx, common.HexToHash("0x1232"), 11, time.Now(), 0)) + require.NoError(t, o1.InsertBlock(ctx, common.HexToHash("0x1233"), 13, time.Now(), 0)) + require.NoError(t, o1.InsertBlock(ctx, common.HexToHash("0x1234"), 15, time.Now(), 0)) + block, err := o1.SelectOldestBlock(ctx, 12) + require.NoError(t, err) + require.NotNil(t, block) + require.Equal(t, block.BlockNumber, int64(13)) + require.Equal(t, block.BlockHash, common.HexToHash("0x1233")) + }) +} diff --git a/core/cmd/blocks_commands.go b/core/cmd/blocks_commands.go index 72b0523e18d..158caf253ab 100644 --- a/core/cmd/blocks_commands.go +++ b/core/cmd/blocks_commands.go @@ -9,6 +9,8 @@ import ( "github.com/pkg/errors" "github.com/urfave/cli" "go.uber.org/multierr" + + "github.com/smartcontractkit/chainlink/v2/core/web" ) func initBlocksSubCmds(s *Shell) []cli.Command { @@ -34,6 +36,18 @@ func initBlocksSubCmds(s *Shell) []cli.Command { }, }, }, + { + Name: "find-lca", + Usage: "Find latest common block stored in DB and on chain", + Action: s.FindLCA, + Flags: []cli.Flag{ + cli.Int64Flag{ + Name: "evm-chain-id", + Usage: "Chain ID of the EVM-based blockchain", + Required: true, + }, + }, + }, } } @@ -75,3 +89,47 @@ func (s *Shell) ReplayFromBlock(c *cli.Context) (err error) { fmt.Println("Replay started") return nil } + +// LCAPresenter implements TableRenderer for an LCAResponse. +type LCAPresenter struct { + web.LCAResponse +} + +// ToRow presents the EVMChainResource as a slice of strings. +func (p *LCAPresenter) ToRow() []string { + return []string{p.EVMChainID.String(), p.Hash, strconv.FormatInt(p.BlockNumber, 10)} +} + +// RenderTable implements TableRenderer +// Just renders a single row +func (p LCAPresenter) RenderTable(rt RendererTable) error { + renderList([]string{"ChainID", "Block Hash", "Block Number"}, [][]string{p.ToRow()}, rt.Writer) + + return nil +} + +// FindLCA finds last common block stored in DB and on chain. +func (s *Shell) FindLCA(c *cli.Context) (err error) { + v := url.Values{} + + if c.IsSet("evm-chain-id") { + v.Add("evmChainID", fmt.Sprintf("%d", c.Int64("evm-chain-id"))) + } + + resp, err := s.HTTP.Get(s.ctx(), + fmt.Sprintf( + "/v2/find_lca?%s", + v.Encode(), + )) + if err != nil { + return s.errorOut(err) + } + + defer func() { + if cerr := resp.Body.Close(); cerr != nil { + err = multierr.Append(err, cerr) + } + }() + + return s.renderAPIResponse(resp, &LCAPresenter{}, "Last Common Ancestor") +} diff --git a/core/cmd/blocks_commands_test.go b/core/cmd/blocks_commands_test.go index 30540748cb1..f7656b94ae1 100644 --- a/core/cmd/blocks_commands_test.go +++ b/core/cmd/blocks_commands_test.go @@ -41,3 +41,28 @@ func Test_ReplayFromBlock(t *testing.T) { c = cli.NewContext(nil, set, nil) require.NoError(t, client.ReplayFromBlock(c)) } + +func Test_FindLCA(t *testing.T) { + t.Parallel() + + //ethClient.On("BalanceAt", mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(42), nil) + app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.EVM[0].ChainID = (*ubig.Big)(big.NewInt(5)) + c.EVM[0].Enabled = ptr(true) + }) + + client, _ := app.NewShellAndRenderer() + + set := flag.NewFlagSet("test", 0) + flagSetApplyFromAction(client.FindLCA, set, "") + + //Incorrect chain ID + require.NoError(t, set.Set("evm-chain-id", "1")) + c := cli.NewContext(nil, set, nil) + require.ErrorContains(t, client.FindLCA(c), "does not match any local chains") + + //Correct chain ID + require.NoError(t, set.Set("evm-chain-id", "5")) + c = cli.NewContext(nil, set, nil) + require.ErrorContains(t, client.FindLCA(c), "FindLCA is only available if LogPoller is enabled") +} diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go index 24cb43e2090..7c9c025d4be 100644 --- a/core/cmd/shell_local.go +++ b/core/cmd/shell_local.go @@ -34,6 +34,7 @@ import ( "github.com/jmoiron/sqlx" cutils "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/build" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" @@ -253,6 +254,23 @@ func initLocalSubCmds(s *Shell, safe bool) []cli.Command { }, }, }, + { + Name: "remove-blocks", + Usage: "Deletes block range and all associated data", + Action: s.RemoveBlocks, + Flags: []cli.Flag{ + cli.IntFlag{ + Name: "start", + Usage: "Beginning of block range to be deleted", + Required: true, + }, + cli.Int64Flag{ + Name: "evm-chain-id", + Usage: "Chain ID of the EVM-based blockchain", + Required: true, + }, + }, + }, } } @@ -1180,3 +1198,64 @@ func insertFixtures(dbURL url.URL, pathToFixtures string) (err error) { _, err = db.Exec(string(fixturesSQL)) return err } + +// RemoveBlocks - removes blocks after the specified blocks number +func (s *Shell) RemoveBlocks(c *cli.Context) error { + start := c.Int64("start") + if start <= 0 { + return s.errorOut(errors.New("Must pass a positive value in '--start' parameter")) + } + + chainID := big.NewInt(0) + if c.IsSet("evm-chain-id") { + err := chainID.UnmarshalText([]byte(c.String("evm-chain-id"))) + if err != nil { + return s.errorOut(err) + } + } + + cfg := s.Config + err := cfg.Validate() + if err != nil { + return s.errorOut(fmt.Errorf("error validating configuration: %+v", err)) + } + + lggr := logger.Sugared(s.Logger.Named("RemoveBlocks")) + ldb := pg.NewLockedDB(cfg.AppID(), cfg.Database(), cfg.Database().Lock(), lggr) + ctx, cancel := context.WithCancel(context.Background()) + go shutdown.HandleShutdown(func(sig string) { + cancel() + lggr.Info("received signal to stop - closing the database and releasing lock") + + if cErr := ldb.Close(); cErr != nil { + lggr.Criticalf("Failed to close LockedDB: %v", cErr) + } + + if cErr := s.CloseLogger(); cErr != nil { + log.Printf("Failed to close Logger: %v", cErr) + } + }) + + if err = ldb.Open(ctx); err != nil { + // If not successful, we know neither locks nor connection remains opened + return s.errorOut(errors.Wrap(err, "opening db")) + } + defer lggr.ErrorIfFn(ldb.Close, "Error closing db") + + // From now on, DB locks and DB connection will be released on every return. + // Keep watching on logger.Fatal* calls and os.Exit(), because defer will not be executed. + + app, err := s.AppFactory.NewApplication(ctx, s.Config, s.Logger, ldb.DB()) + if err != nil { + return s.errorOut(errors.Wrap(err, "fatal error instantiating application")) + } + + err = app.DeleteLogPollerDataAfter(ctx, chainID, start) + if err != nil { + return s.errorOut(err) + } + + lggr.Infof("RemoveBlocks: successfully removed blocks") + + return nil +} diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index 7427e6caedb..e7322e513ae 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -2,6 +2,7 @@ package cmd_test import ( "flag" + "fmt" "math/big" "os" "strconv" @@ -514,3 +515,58 @@ func TestShell_CleanupChainTables(t *testing.T) { c := cli.NewContext(nil, set, nil) require.NoError(t, client.CleanupChainTables(c)) } + +func TestShell_RemoveBlocks(t *testing.T) { + db := pgtest.NewSqlxDB(t) + cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + s.Password.Keystore = models.NewSecret("dummy") + c.EVM[0].Nodes[0].Name = ptr("fake") + c.EVM[0].Nodes[0].HTTPURL = commonconfig.MustParseURL("http://fake.com") + c.EVM[0].Nodes[0].WSURL = commonconfig.MustParseURL("WSS://fake.com/ws") + // seems to be needed for config validate + c.Insecure.OCRDevelopmentMode = nil + }) + + lggr := logger.TestLogger(t) + + app := mocks.NewApplication(t) + app.On("GetSqlxDB").Maybe().Return(db) + shell := cmd.Shell{ + Config: cfg, + AppFactory: cltest.InstanceAppFactory{App: app}, + FallbackAPIInitializer: cltest.NewMockAPIInitializer(t), + Runner: cltest.EmptyRunner{}, + Logger: lggr, + } + + t.Run("Returns error, if --start is not positive", func(t *testing.T) { + set := flag.NewFlagSet("test", 0) + flagSetApplyFromAction(shell.RemoveBlocks, set, "") + require.NoError(t, set.Set("start", "0")) + require.NoError(t, set.Set("evm-chain-id", "12")) + c := cli.NewContext(nil, set, nil) + err := shell.RemoveBlocks(c) + require.ErrorContains(t, err, "Must pass a positive value in '--start' parameter") + }) + t.Run("Returns error, if removal fails", func(t *testing.T) { + set := flag.NewFlagSet("test", 0) + flagSetApplyFromAction(shell.RemoveBlocks, set, "") + require.NoError(t, set.Set("start", "10000")) + require.NoError(t, set.Set("evm-chain-id", "12")) + expectedError := fmt.Errorf("failed to delete log poller's data") + app.On("DeleteLogPollerDataAfter", mock.Anything, big.NewInt(12), int64(10000)).Return(expectedError).Once() + c := cli.NewContext(nil, set, nil) + err := shell.RemoveBlocks(c) + require.ErrorContains(t, err, expectedError.Error()) + }) + t.Run("Happy path", func(t *testing.T) { + set := flag.NewFlagSet("test", 0) + flagSetApplyFromAction(shell.RemoveBlocks, set, "") + require.NoError(t, set.Set("start", "10000")) + require.NoError(t, set.Set("evm-chain-id", "12")) + app.On("DeleteLogPollerDataAfter", mock.Anything, big.NewInt(12), int64(10000)).Return(nil).Once() + c := cli.NewContext(nil, set, nil) + err := shell.RemoveBlocks(c) + require.NoError(t, err) + }) +} diff --git a/core/internal/mocks/application.go b/core/internal/mocks/application.go index c83b37a0e5d..f845d46ca8d 100644 --- a/core/internal/mocks/application.go +++ b/core/internal/mocks/application.go @@ -23,6 +23,8 @@ import ( logger "github.com/smartcontractkit/chainlink/v2/core/logger" + logpoller "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + mock "github.com/stretchr/testify/mock" pipeline "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" @@ -147,6 +149,24 @@ func (_m *Application) DeleteJob(ctx context.Context, jobID int32) error { return r0 } +// DeleteLogPollerDataAfter provides a mock function with given fields: ctx, chainID, start +func (_m *Application) DeleteLogPollerDataAfter(ctx context.Context, chainID *big.Int, start int64) error { + ret := _m.Called(ctx, chainID, start) + + if len(ret) == 0 { + panic("no return value specified for DeleteLogPollerDataAfter") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, int64) error); ok { + r0 = rf(ctx, chainID, start) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // EVMORM provides a mock function with given fields: func (_m *Application) EVMORM() types.Configs { ret := _m.Called() @@ -167,6 +187,36 @@ func (_m *Application) EVMORM() types.Configs { return r0 } +// FindLCA provides a mock function with given fields: ctx, chainID +func (_m *Application) FindLCA(ctx context.Context, chainID *big.Int) (*logpoller.LogPollerBlock, error) { + ret := _m.Called(ctx, chainID) + + if len(ret) == 0 { + panic("no return value specified for FindLCA") + } + + var r0 *logpoller.LogPollerBlock + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) (*logpoller.LogPollerBlock, error)); ok { + return rf(ctx, chainID) + } + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) *logpoller.LogPollerBlock); ok { + r0 = rf(ctx, chainID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*logpoller.LogPollerBlock) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { + r1 = rf(ctx, chainID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetAuditLogger provides a mock function with given fields: func (_m *Application) GetAuditLogger() audit.AuditLogger { ret := _m.Called() diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index 2aebef3f8f7..ae3db2e7a73 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -22,7 +22,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink-common/pkg/utils/jsonserializable" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink/v2/core/capabilities" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/static" "github.com/smartcontractkit/chainlink/v2/core/bridges" @@ -115,6 +117,11 @@ type Application interface { ID() uuid.UUID SecretGenerator() SecretGenerator + + // FindLCA - finds last common ancestor for LogPoller's chain available in the database and RPC chain + FindLCA(ctx context.Context, chainID *big.Int) (*logpoller.LogPollerBlock, error) + // DeleteLogPollerDataAfter - delete LogPoller state starting from the specified block + DeleteLogPollerDataAfter(ctx context.Context, chainID *big.Int, start int64) error } // ChainlinkApplication contains fields for the JobSubscriber, Scheduler, @@ -886,3 +893,39 @@ func (app *ChainlinkApplication) GetWebAuthnConfiguration() sessions.WebAuthnCon func (app *ChainlinkApplication) ID() uuid.UUID { return app.Config.AppID() } + +// FindLCA - finds last common ancestor +func (app *ChainlinkApplication) FindLCA(ctx context.Context, chainID *big.Int) (*logpoller.LogPollerBlock, error) { + chain, err := app.GetRelayers().LegacyEVMChains().Get(chainID.String()) + if err != nil { + return nil, err + } + if !app.Config.Feature().LogPoller() { + return nil, fmt.Errorf("FindLCA is only available if LogPoller is enabled") + } + + lca, err := chain.LogPoller().FindLCA(ctx) + if err != nil { + return nil, fmt.Errorf("failed to find lca: %w", err) + } + + return lca, nil +} + +// DeleteLogPollerDataAfter - delete LogPoller state starting from the specified block +func (app *ChainlinkApplication) DeleteLogPollerDataAfter(ctx context.Context, chainID *big.Int, start int64) error { + chain, err := app.GetRelayers().LegacyEVMChains().Get(chainID.String()) + if err != nil { + return err + } + if !app.Config.Feature().LogPoller() { + return fmt.Errorf("DeleteLogPollerDataAfter is only available if LogPoller is enabled") + } + + err = chain.LogPoller().DeleteLogsAndBlocksAfter(ctx, start) + if err != nil { + return fmt.Errorf("failed to recover LogPoller: %w", err) + } + + return nil +} diff --git a/core/web/api.go b/core/web/api.go index 1f97d59c77d..51f7b855cd5 100644 --- a/core/web/api.go +++ b/core/web/api.go @@ -120,7 +120,7 @@ func ParsePaginatedResponse(input []byte, resource interface{}, links *jsonapi.L func parsePaginatedResponseToDocument(input []byte, resource interface{}, document *jsonapi.Document) error { err := ParseJSONAPIResponse(input, resource) if err != nil { - return errors.Wrap(err, "ParseJSONAPIResponse error") + return errors.Wrapf(err, "ParseJSONAPIResponse error body: %s", string(input)) } // Unmarshal using the stdlib Unmarshal to extract the links part of the document diff --git a/core/web/lca_controller.go b/core/web/lca_controller.go new file mode 100644 index 00000000000..bb4866c3d08 --- /dev/null +++ b/core/web/lca_controller.go @@ -0,0 +1,74 @@ +package web + +import ( + "errors" + "fmt" + "net/http" + + "github.com/gin-gonic/gin" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" +) + +type LCAController struct { + App chainlink.Application +} + +// FindLCA compares chain of blocks available in the DB with chain provided by an RPC and returns last common ancestor +// Example: +// +// "/v2/find_lca" +func (bdc *LCAController) FindLCA(c *gin.Context) { + chain, err := getChain(bdc.App.GetRelayers().LegacyEVMChains(), c.Query("evmChainID")) + if err != nil { + if errors.Is(err, ErrInvalidChainID) || errors.Is(err, ErrMultipleChains) || errors.Is(err, ErrMissingChainID) { + jsonAPIError(c, http.StatusUnprocessableEntity, err) + return + } + jsonAPIError(c, http.StatusInternalServerError, err) + return + } + chainID := chain.ID() + + lca, err := bdc.App.FindLCA(c.Request.Context(), chainID) + if err != nil { + jsonAPIError(c, http.StatusInternalServerError, err) + return + } + + if lca == nil { + jsonAPIError(c, http.StatusNotFound, fmt.Errorf("failed to find last common ancestor")) + return + } + + response := LCAResponse{ + BlockNumber: lca.BlockNumber, + Hash: lca.BlockHash.String(), + EVMChainID: big.New(chainID), + } + jsonAPIResponse(c, &response, "response") + +} + +type LCAResponse struct { + BlockNumber int64 `json:"blockNumber"` + Hash string `json:"hash"` + EVMChainID *big.Big `json:"evmChainID"` +} + +// GetID returns the jsonapi ID. +func (s LCAResponse) GetID() string { + return "LCAResponseID" +} + +// GetName returns the collection name for jsonapi. +func (LCAResponse) GetName() string { + return "lca_response" +} + +// SetID is used to conform to the UnmarshallIdentifier interface for +// deserializing from jsonapi documents. +func (*LCAResponse) SetID(string) error { + return nil +} diff --git a/core/web/lca_controller_test.go b/core/web/lca_controller_test.go new file mode 100644 index 00000000000..7ec476e8eca --- /dev/null +++ b/core/web/lca_controller_test.go @@ -0,0 +1,29 @@ +package web_test + +import ( + _ "embed" + "io" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" +) + +func TestLCAController_FindLCA(t *testing.T) { + cfg := configtest.NewTestGeneralConfig(t) + ec := setupEthClientForControllerTests(t) + app := cltest.NewApplicationWithConfigAndKey(t, cfg, cltest.DefaultP2PKey, ec) + require.NoError(t, app.Start(testutils.Context(t))) + client := app.NewHTTPClient(nil) + resp, cleanup := client.Get("/v2/find_lca?evmChainID=1") + t.Cleanup(cleanup) + assert.Equal(t, http.StatusUnprocessableEntity, resp.StatusCode) + b, err := io.ReadAll(resp.Body) + require.NoError(t, err) + assert.Contains(t, string(b), "chain id does not match any local chains") +} diff --git a/core/web/router.go b/core/web/router.go index c327583a005..158ea4b411f 100644 --- a/core/web/router.go +++ b/core/web/router.go @@ -292,6 +292,8 @@ func v2Routes(app chainlink.Application, r *gin.RouterGroup) { rc := ReplayController{app} authv2.POST("/replay_from_block/:number", auth.RequiresRunRole(rc.ReplayFromBlock)) + lcaC := LCAController{app} + authv2.GET("/find_lca", auth.RequiresRunRole(lcaC.FindLCA)) csakc := CSAKeysController{app} authv2.GET("/keys/csa", csakc.Index) diff --git a/testdata/scripts/blocks/help.txtar b/testdata/scripts/blocks/help.txtar index 55aaf71858d..5d362a082fd 100644 --- a/testdata/scripts/blocks/help.txtar +++ b/testdata/scripts/blocks/help.txtar @@ -9,7 +9,8 @@ USAGE: chainlink blocks command [command options] [arguments...] COMMANDS: - replay Replays block data from the given number + replay Replays block data from the given number + find-lca Find latest common block stored in DB and on chain OPTIONS: --help, -h show help diff --git a/testdata/scripts/help-all/help-all.txtar b/testdata/scripts/help-all/help-all.txtar index eeaf0da98d1..e111295abb4 100644 --- a/testdata/scripts/help-all/help-all.txtar +++ b/testdata/scripts/help-all/help-all.txtar @@ -16,6 +16,7 @@ admin users list # Lists all API users and their roles attempts # Commands for managing Ethereum Transaction Attempts attempts list # List the Transaction Attempts in descending order blocks # Commands for managing blocks +blocks find-lca # Find latest common block stored in DB and on chain blocks replay # Replays block data from the given number bridges # Commands for Bridges communicating with External Adapters bridges create # Create a new Bridge to an External Adapter @@ -132,6 +133,7 @@ node db status # Display the current database migration status. node db version # Display the current database version. node profile # Collects profile metrics from the node. node rebroadcast-transactions # Manually rebroadcast txs matching nonce range with the specified gas price. This is useful in emergencies e.g. high gas prices and/or network congestion to forcibly clear out the pending TX queue +node remove-blocks # Deletes block range and all associated data node start # Run the Chainlink node node status # Displays the health of various services running inside the node. node validate # Validate the TOML configuration and secrets that are passed as flags to the `node` command. Prints the full effective configuration, with defaults included diff --git a/testdata/scripts/node/help.txtar b/testdata/scripts/node/help.txtar index 33e1fdc90bc..875500b13df 100644 --- a/testdata/scripts/node/help.txtar +++ b/testdata/scripts/node/help.txtar @@ -13,6 +13,7 @@ COMMANDS: rebroadcast-transactions Manually rebroadcast txs matching nonce range with the specified gas price. This is useful in emergencies e.g. high gas prices and/or network congestion to forcibly clear out the pending TX queue validate Validate the TOML configuration and secrets that are passed as flags to the `node` command. Prints the full effective configuration, with defaults included db Commands for managing the database. + remove-blocks Deletes block range and all associated data OPTIONS: --config value, -c value TOML configuration file(s) via flag, or raw TOML via env var. If used, legacy env vars must not be set. Multiple files can be used (-c configA.toml -c configB.toml), and they are applied in order with duplicated fields overriding any earlier values. If the 'CL_CONFIG' env var is specified, it is always processed last with the effect of being the final override. [$CL_CONFIG] From 71eed2133fb86a065461787e31db5fb1b18b05de Mon Sep 17 00:00:00 2001 From: Tate Date: Fri, 26 Apr 2024 08:47:17 -0600 Subject: [PATCH 27/34] Fix Node Migration Test Check For Versions (#12982) --- .../action.yml | 1 + .github/workflows/integration-tests.yml | 90 ++++++++----------- 2 files changed, 40 insertions(+), 51 deletions(-) diff --git a/.github/actions/setup-create-base64-upgrade-config/action.yml b/.github/actions/setup-create-base64-upgrade-config/action.yml index ed25fd6375f..8f514784725 100644 --- a/.github/actions/setup-create-base64-upgrade-config/action.yml +++ b/.github/actions/setup-create-base64-upgrade-config/action.yml @@ -92,6 +92,7 @@ runs: [ChainlinkUpgradeImage] image="$UPGRADE_IMAGE" version="$UPGRADE_VERSION" + postgres_version="$CHAINLINK_POSTGRES_VERSION" [Logging] test_log_collect=$test_log_collect diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 1f3e093cfdc..8dcf32b127e 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -218,40 +218,6 @@ jobs: AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} dep_evm_sha: ${{ inputs.evm-ref }} - build-test-image: - if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'schedule' || contains(join(github.event.pull_request.labels.*.name, ' '), 'build-test-image') - environment: integration - permissions: - id-token: write - contents: read - name: Build Test Image - runs-on: ubuntu22.04-16cores-64GB - needs: [changes] - steps: - - name: Collect Metrics - if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 - with: - id: ${{ env.COLLECTION_ID }}-build-test-image - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Build Test Image - continue-on-error: true - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - repository: smartcontractkit/chainlink - ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Build Test Image - if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - uses: ./.github/actions/build-test-image - with: - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - compare-tests: needs: [changes] runs-on: ubuntu-latest @@ -726,7 +692,7 @@ jobs: cache_restore_only: "true" QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} + QA_KUBECONFIG: "" should_tidy: "false" - name: Show Otel-Collector Logs if: steps.check-label.outputs.trace == 'true' && matrix.product.name == 'ocr2' && matrix.product.tag_suffix == '-plugins' @@ -830,6 +796,7 @@ jobs: # Run the setup if the matrix finishes but this time save the cache if we have a cache hit miss # this will also only run if both of the matrix jobs pass eth-smoke-go-mod-cache: + environment: integration needs: [eth-smoke-tests] runs-on: ubuntu-latest @@ -863,7 +830,7 @@ jobs: id-token: write contents: read runs-on: ubuntu-latest - needs: [build-chainlink, changes, build-test-image] + needs: [build-chainlink, changes] # Only run migration tests on new tags if: startsWith(github.ref, 'refs/tags/') env: @@ -876,6 +843,17 @@ jobs: TEST_LOG_LEVEL: debug TEST_SUITE: migration steps: + - name: Collect Metrics + id: collect-gha-metrics + uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 + with: + id: ${{ env.COLLECTION_ID }}-migration-tests + org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} + this-job-name: Version Migration Tests + test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' + continue-on-error: true - name: Checkout the repo uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 with: @@ -886,7 +864,12 @@ jobs: run: | untrimmed_ver=$(curl --header "Authorization: token ${{ secrets.GITHUB_TOKEN }}" --request GET https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r .name) latest_version="${untrimmed_ver:1}" - echo "latest_version=${latest_version} | tee -a $GITHUB_OUTPUT" + # Check if latest_version is empty + if [ -z "$latest_version" ]; then + echo "Error: The latest_version is empty. The migration tests need a verison to run." + exit 1 + fi + echo "latest_version=${latest_version}" >> "$GITHUB_OUTPUT" - name: Name Versions run: | echo "Running migration tests from version '${{ steps.get_latest_version.outputs.latest_version }}' to: '${{ inputs.evm-ref || github.sha }}'" @@ -898,13 +881,22 @@ jobs: chainlinkVersion: ${{ steps.get_latest_version.outputs.latest_version }} upgradeImage: ${{ env.UPGRADE_IMAGE }} upgradeVersion: ${{ env.UPGRADE_VERSION }} + runId: ${{ github.run_id }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} + lokiEndpoint: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push + lokiTenantId: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + lokiBasicAuth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: ${{ vars.GRAFANA_URL }} + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - name: Run Migration Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@519851800779323566b7b7c22cc21bff95dbb639 # v2.3.11 with: - test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json ./migration 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage + test_command_to_run: cd ./integration-tests && go test -timeout 20m -count=1 -json ./migration 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage test_download_vendor_packages_command: cd ./integration-tests && go mod download cl_repo: ${{ env.CHAINLINK_IMAGE }} cl_image_tag: ${{ steps.get_latest_version.outputs.latest_version }} + aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} artifacts_name: node-migration-test-logs artifacts_location: | ./integration-tests/migration/logs @@ -916,28 +908,24 @@ jobs: cache_restore_only: "true" QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} + QA_KUBECONFIG: "" go_coverage_src_dir: /var/tmp/go-coverage go_coverage_dest_dir: ${{ github.workspace }}/.covdata + should_tidy: "false" - name: Upload Coverage Data uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: cl-node-coverage-data-migration-tests path: .covdata retention-days: 1 - - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 + - name: Notify Slack + if: failure() && github.event_name != 'workflow_dispatch' + uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 + env: + SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} with: - id: ${{ env.COLLECTION_ID }}-migration-tests - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Version Migration Tests - test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' - continue-on-error: true + channel-id: "#team-test-tooling-internal" + slack-message: ":x: :mild-panic-intensifies: Node Migration Tests Failed: ${{ job.html_url }}\n${{ format('https://github.com/smartcontractkit/chainlink/actions/runs/{0}', github.run_id) }}" ## Solana Section get_solana_sha: From b1c8d74272e3b02e0a2a954c3d61b65ecb42f5cf Mon Sep 17 00:00:00 2001 From: Gabriel Paradiso Date: Fri, 26 Apr 2024 16:53:31 +0200 Subject: [PATCH 28/34] fix: prevent query syntax error if allowlist is empty (#12912) Co-authored-by: Morgan Kuphal <87319522+KuphJr@users.noreply.github.com> --- .../services/gateway/handlers/functions/allowlist/orm.go | 5 +++++ .../gateway/handlers/functions/allowlist/orm_test.go | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/core/services/gateway/handlers/functions/allowlist/orm.go b/core/services/gateway/handlers/functions/allowlist/orm.go index 7867c06d5d4..20a8ed15252 100644 --- a/core/services/gateway/handlers/functions/allowlist/orm.go +++ b/core/services/gateway/handlers/functions/allowlist/orm.go @@ -67,6 +67,11 @@ func (o *orm) GetAllowedSenders(ctx context.Context, offset, limit uint) ([]comm } func (o *orm) CreateAllowedSenders(ctx context.Context, allowedSenders []common.Address) error { + if len(allowedSenders) == 0 { + o.lggr.Debugf("empty allowed senders list: %v for routerContractAddress: %s. skipping...", allowedSenders, o.routerContractAddress) + return nil + } + var valuesPlaceholder []string for i := 1; i <= len(allowedSenders)*2; i += 2 { valuesPlaceholder = append(valuesPlaceholder, fmt.Sprintf("($%d, $%d)", i, i+1)) diff --git a/core/services/gateway/handlers/functions/allowlist/orm_test.go b/core/services/gateway/handlers/functions/allowlist/orm_test.go index 2584e131968..388d47a769b 100644 --- a/core/services/gateway/handlers/functions/allowlist/orm_test.go +++ b/core/services/gateway/handlers/functions/allowlist/orm_test.go @@ -128,6 +128,15 @@ func TestORM_CreateAllowedSenders(t *testing.T) { require.Equal(t, expected[0], results[0]) require.Equal(t, expected[1], results[1]) }) + + // this scenario can happen if the allowlist is empty but we call CreateAllowedSenders + t.Run("OK-empty_list", func(t *testing.T) { + ctx := testutils.Context(t) + orm, err := setupORM(t) + require.NoError(t, err) + err = orm.CreateAllowedSenders(ctx, []common.Address{}) + require.NoError(t, err) + }) } func TestORM_DeleteAllowedSenders(t *testing.T) { From 0370aa94fbb236ce7ba268adf9a669831b0b40af Mon Sep 17 00:00:00 2001 From: frank zhu Date: Fri, 26 Apr 2024 09:23:44 -0700 Subject: [PATCH 29/34] update contracts README with changesets (#13002) * update contracts README with changesets * add date for 1.1.0 release * update with more explicit direction --- contracts/CHANGELOG.md | 4 ++-- contracts/README.md | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/contracts/CHANGELOG.md b/contracts/CHANGELOG.md index 667a5ad2529..3139312e325 100644 --- a/contracts/CHANGELOG.md +++ b/contracts/CHANGELOG.md @@ -1,6 +1,6 @@ -# @chainlink/contracts CHANGELOG.md +# @chainlink/contracts -## 1.1.0 +## 1.1.0 - 2024-04-23 ### Minor Changes diff --git a/contracts/README.md b/contracts/README.md index 8df69057229..26b0a823298 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -50,6 +50,22 @@ contribution information. Thank you! +### Changesets + +We use [changesets](https://github.com/changesets/changesets) to manage versioning the contracts. + +Every PR that modifies any configuration or code, should most likely accompanied by a changeset file. + +To install `changesets`: + 1. Install `pnpm` if it is not already installed - [docs](https://pnpm.io/installation). + 2. Run `pnpm install`. + +Either after or before you create a commit, run the `pnpm changeset` command in the `contracts` directory to create an accompanying changeset entry which will reflect on the CHANGELOG for the next release. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), + +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + ## License [MIT](https://choosealicense.com/licenses/mit/) From bcf76534862b32503f4192e38b7e1cb4dd7e312d Mon Sep 17 00:00:00 2001 From: Dmytro Haidashenko <34754799+dhaidashenko@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:27:54 +0200 Subject: [PATCH 30/34] Wrap RPC errors (#12638) * Tag errors with msg that RPC Client returned the error and include RPC name * changeset * added tag to the changeset --- .changeset/quick-fishes-heal.md | 5 + common/client/models.go | 29 ++++ common/client/models_test.go | 16 ++ common/client/multi_node.go | 13 +- common/client/multi_node_test.go | 20 ++- core/chains/evm/client/rpc_client.go | 157 ++++++------------ core/chains/evm/client/sub_error_wrapper.go | 77 +++++++++ .../evm/client/sub_error_wrapper_test.go | 75 +++++++++ .../chains/evm/gas/block_history_estimator.go | 2 +- 9 files changed, 275 insertions(+), 119 deletions(-) create mode 100644 .changeset/quick-fishes-heal.md create mode 100644 common/client/models_test.go create mode 100644 core/chains/evm/client/sub_error_wrapper.go create mode 100644 core/chains/evm/client/sub_error_wrapper_test.go diff --git a/.changeset/quick-fishes-heal.md b/.changeset/quick-fishes-heal.md new file mode 100644 index 00000000000..966e74c843a --- /dev/null +++ b/.changeset/quick-fishes-heal.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- +#changed +Added prefix `RPCClient returned error ({RPC_NAME})` to RPC errors to simplify filtering of RPC related issues. diff --git a/common/client/models.go b/common/client/models.go index 66f1e9cf88b..fd0c3915940 100644 --- a/common/client/models.go +++ b/common/client/models.go @@ -28,6 +28,35 @@ var sendTxSevereErrors = []SendTxReturnCode{Fatal, Underpriced, Unsupported, Exc // sendTxSuccessfulCodes - error codes which signal that transaction was accepted by the node var sendTxSuccessfulCodes = []SendTxReturnCode{Successful, TransactionAlreadyKnown} +func (c SendTxReturnCode) String() string { + switch c { + case Successful: + return "Successful" + case Fatal: + return "Fatal" + case Retryable: + return "Retryable" + case Underpriced: + return "Underpriced" + case Unknown: + return "Unknown" + case Unsupported: + return "Unsupported" + case TransactionAlreadyKnown: + return "TransactionAlreadyKnown" + case InsufficientFunds: + return "InsufficientFunds" + case ExceedsMaxFee: + return "ExceedsMaxFee" + case FeeOutOfValidRange: + return "FeeOutOfValidRange" + case OutOfCounters: + return "OutOfCounters" + default: + return fmt.Sprintf("SendTxReturnCode(%d)", c) + } +} + type NodeTier int const ( diff --git a/common/client/models_test.go b/common/client/models_test.go new file mode 100644 index 00000000000..2d5dc31b373 --- /dev/null +++ b/common/client/models_test.go @@ -0,0 +1,16 @@ +package client + +import ( + "strings" + "testing" +) + +func TestSendTxReturnCode_String(t *testing.T) { + // ensure all the SendTxReturnCodes have proper name + for c := 1; c < int(sendTxReturnCodeLen); c++ { + strC := SendTxReturnCode(c).String() + if strings.Contains(strC, "SendTxReturnCode(") { + t.Errorf("Expected %s to have a proper string representation", strC) + } + } +} diff --git a/common/client/multi_node.go b/common/client/multi_node.go index cc8daed599c..fa413df91aa 100644 --- a/common/client/multi_node.go +++ b/common/client/multi_node.go @@ -561,6 +561,13 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP return n.RPC().PendingSequenceAt(ctx, addr) } +type sendTxErrors map[SendTxReturnCode][]error + +// String - returns string representation of the errors map. Required by logger to properly represent the value +func (errs sendTxErrors) String() string { + return fmt.Sprint(map[SendTxReturnCode][]error(errs)) +} + func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) SendEmptyTransaction( ctx context.Context, newTxAttempt func(seq SEQ, feeLimit uint32, fee FEE, fromAddress ADDR) (attempt any, err error), @@ -602,7 +609,7 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP ctx, cancel := c.chStop.Ctx(ctx) defer cancel() requiredResults := int(math.Ceil(float64(healthyNodesNum) * sendTxQuorum)) - errorsByCode := map[SendTxReturnCode][]error{} + errorsByCode := sendTxErrors{} var softTimeoutChan <-chan time.Time var resultsCount int loop: @@ -639,7 +646,7 @@ loop: func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OPS, TX_RECEIPT, FEE, HEAD, RPC_CLIENT, BATCH_ELEM]) reportSendTxAnomalies(tx TX, txResults <-chan sendTxResult) { defer c.wg.Done() - resultsByCode := map[SendTxReturnCode][]error{} + resultsByCode := sendTxErrors{} // txResults eventually will be closed for txResult := range txResults { resultsByCode[txResult.ResultCode] = append(resultsByCode[txResult.ResultCode], txResult.Err) @@ -653,7 +660,7 @@ func (c *multiNode[CHAIN_ID, SEQ, ADDR, BLOCK_HASH, TX, TX_HASH, EVENT, EVENT_OP } } -func aggregateTxResults(resultsByCode map[SendTxReturnCode][]error) (txResult error, err error) { +func aggregateTxResults(resultsByCode sendTxErrors) (txResult error, err error) { severeErrors, hasSevereErrors := findFirstIn(resultsByCode, sendTxSevereErrors) successResults, hasSuccess := findFirstIn(resultsByCode, sendTxSuccessfulCodes) if hasSuccess { diff --git a/common/client/multi_node_test.go b/common/client/multi_node_test.go index 9c09bd57d70..9f6904fcaf2 100644 --- a/common/client/multi_node_test.go +++ b/common/client/multi_node_test.go @@ -796,13 +796,13 @@ func TestMultiNode_SendTransaction_aggregateTxResults(t *testing.T) { Name string ExpectedTxResult string ExpectedCriticalErr string - ResultsByCode map[SendTxReturnCode][]error + ResultsByCode sendTxErrors }{ { Name: "Returns success and logs critical error on success and Fatal", ExpectedTxResult: "success", ExpectedCriticalErr: "found contradictions in nodes replies on SendTransaction: got success and severe error", - ResultsByCode: map[SendTxReturnCode][]error{ + ResultsByCode: sendTxErrors{ Successful: {errors.New("success")}, Fatal: {errors.New("fatal")}, }, @@ -811,7 +811,7 @@ func TestMultiNode_SendTransaction_aggregateTxResults(t *testing.T) { Name: "Returns TransactionAlreadyKnown and logs critical error on TransactionAlreadyKnown and Fatal", ExpectedTxResult: "tx_already_known", ExpectedCriticalErr: "found contradictions in nodes replies on SendTransaction: got success and severe error", - ResultsByCode: map[SendTxReturnCode][]error{ + ResultsByCode: sendTxErrors{ TransactionAlreadyKnown: {errors.New("tx_already_known")}, Unsupported: {errors.New("unsupported")}, }, @@ -820,7 +820,7 @@ func TestMultiNode_SendTransaction_aggregateTxResults(t *testing.T) { Name: "Prefers sever error to temporary", ExpectedTxResult: "underpriced", ExpectedCriticalErr: "", - ResultsByCode: map[SendTxReturnCode][]error{ + ResultsByCode: sendTxErrors{ Retryable: {errors.New("retryable")}, Underpriced: {errors.New("underpriced")}, }, @@ -829,7 +829,7 @@ func TestMultiNode_SendTransaction_aggregateTxResults(t *testing.T) { Name: "Returns temporary error", ExpectedTxResult: "retryable", ExpectedCriticalErr: "", - ResultsByCode: map[SendTxReturnCode][]error{ + ResultsByCode: sendTxErrors{ Retryable: {errors.New("retryable")}, }, }, @@ -837,7 +837,7 @@ func TestMultiNode_SendTransaction_aggregateTxResults(t *testing.T) { Name: "Insufficient funds is treated as error", ExpectedTxResult: "", ExpectedCriticalErr: "", - ResultsByCode: map[SendTxReturnCode][]error{ + ResultsByCode: sendTxErrors{ Successful: {nil}, InsufficientFunds: {errors.New("insufficientFunds")}, }, @@ -846,13 +846,13 @@ func TestMultiNode_SendTransaction_aggregateTxResults(t *testing.T) { Name: "Logs critical error on empty ResultsByCode", ExpectedTxResult: "expected at least one response on SendTransaction", ExpectedCriticalErr: "expected at least one response on SendTransaction", - ResultsByCode: map[SendTxReturnCode][]error{}, + ResultsByCode: sendTxErrors{}, }, { Name: "Zk out of counter error", ExpectedTxResult: "not enough keccak counters to continue the execution", ExpectedCriticalErr: "", - ResultsByCode: map[SendTxReturnCode][]error{ + ResultsByCode: sendTxErrors{ OutOfCounters: {errors.New("not enough keccak counters to continue the execution")}, }, }, @@ -870,6 +870,9 @@ func TestMultiNode_SendTransaction_aggregateTxResults(t *testing.T) { assert.EqualError(t, txResult, testCase.ExpectedTxResult) } + logger.Sugared(logger.Test(t)).Info("Map: " + fmt.Sprint(testCase.ResultsByCode)) + logger.Sugared(logger.Test(t)).Criticalw("observed invariant violation on SendTransaction", "resultsByCode", testCase.ResultsByCode, "err", err) + if testCase.ExpectedCriticalErr == "" { assert.NoError(t, err) } else { @@ -884,5 +887,4 @@ func TestMultiNode_SendTransaction_aggregateTxResults(t *testing.T) { delete(codesToCover, codeToIgnore) } assert.Empty(t, codesToCover, "all of the SendTxReturnCode must be covered by this test") - } diff --git a/core/chains/evm/client/rpc_client.go b/core/chains/evm/client/rpc_client.go index 255b038037a..548acf3206c 100644 --- a/core/chains/evm/client/rpc_client.go +++ b/core/chains/evm/client/rpc_client.go @@ -130,7 +130,7 @@ func (r *rpcClient) Dial(callerCtx context.Context) error { wsrpc, err := rpc.DialWebsocket(ctx, r.ws.uri.String(), "") if err != nil { promEVMPoolRPCNodeDialsFailed.WithLabelValues(r.chainID.String(), r.name).Inc() - return pkgerrors.Wrapf(err, "error while dialing websocket: %v", r.ws.uri.Redacted()) + return r.wrapRPCClientError(pkgerrors.Wrapf(err, "error while dialing websocket: %v", r.ws.uri.Redacted())) } r.ws.rpc = wsrpc @@ -159,7 +159,7 @@ func (r *rpcClient) DialHTTP() error { httprpc, err := rpc.DialHTTP(r.http.uri.String()) if err != nil { promEVMPoolRPCNodeDialsFailed.WithLabelValues(r.chainID.String(), r.name).Inc() - return pkgerrors.Wrapf(err, "error while dialing HTTP: %v", r.http.uri.Redacted()) + return r.wrapRPCClientError(pkgerrors.Wrapf(err, "error while dialing HTTP: %v", r.http.uri.Redacted())) } r.http.rpc = httprpc @@ -295,10 +295,7 @@ func (r *rpcClient) UnsubscribeAllExceptAliveLoop() { // CallContext implementation func (r *rpcClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With( "method", method, @@ -307,6 +304,7 @@ func (r *rpcClient) CallContext(ctx context.Context, result interface{}, method lggr.Debug("RPC call: evmclient.Client#CallContext") start := time.Now() + var err error if http != nil { err = r.wrapHTTP(http.rpc.CallContext(ctx, result, method, args...)) } else { @@ -320,15 +318,13 @@ func (r *rpcClient) CallContext(ctx context.Context, result interface{}, method } func (r *rpcClient) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("nBatchElems", len(b), "batchElems", b) lggr.Trace("RPC call: evmclient.Client#BatchCallContext") start := time.Now() + var err error if http != nil { err = r.wrapHTTP(http.rpc.BatchCallContext(ctx, b)) } else { @@ -342,24 +338,23 @@ func (r *rpcClient) BatchCallContext(ctx context.Context, b []rpc.BatchElem) err } func (r *rpcClient) Subscribe(ctx context.Context, channel chan<- *evmtypes.Head, args ...interface{}) (commontypes.Subscription, error) { - ctx, cancel, ws, _, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, _ := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("args", args) lggr.Debug("RPC call: evmclient.Client#EthSubscribe") start := time.Now() + var sub commontypes.Subscription sub, err := ws.rpc.EthSubscribe(ctx, channel, args...) if err == nil { + sub = newSubscriptionErrorWrapper(sub, r.rpcClientErrorPrefix()) r.registerSub(sub) } duration := time.Since(start) r.logResult(lggr, err, duration, r.getRPCDomain(), "EthSubscribe") - return sub, err + return sub, r.wrapWS(err) } // GethClient wrappers @@ -370,17 +365,14 @@ func (r *rpcClient) TransactionReceipt(ctx context.Context, txHash common.Hash) return nil, err } if receipt == nil { - err = ethereum.NotFound + err = r.wrapRPCClientError(ethereum.NotFound) return } return } func (r *rpcClient) TransactionReceiptGeth(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("txHash", txHash) @@ -403,10 +395,7 @@ func (r *rpcClient) TransactionReceiptGeth(ctx context.Context, txHash common.Ha return } func (r *rpcClient) TransactionByHash(ctx context.Context, txHash common.Hash) (tx *types.Transaction, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("txHash", txHash) @@ -430,10 +419,7 @@ func (r *rpcClient) TransactionByHash(ctx context.Context, txHash common.Hash) ( } func (r *rpcClient) HeaderByNumber(ctx context.Context, number *big.Int) (header *types.Header, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("number", number) @@ -454,10 +440,7 @@ func (r *rpcClient) HeaderByNumber(ctx context.Context, number *big.Int) (header } func (r *rpcClient) HeaderByHash(ctx context.Context, hash common.Hash) (header *types.Header, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("hash", hash) @@ -494,7 +477,7 @@ func (r *rpcClient) blockByNumber(ctx context.Context, number string) (head *evm return nil, err } if head == nil { - err = ethereum.NotFound + err = r.wrapRPCClientError(ethereum.NotFound) return } head.EVMChainID = ubig.New(r.chainID) @@ -507,7 +490,7 @@ func (r *rpcClient) BlockByHash(ctx context.Context, hash common.Hash) (head *ev return nil, err } if head == nil { - err = ethereum.NotFound + err = r.wrapRPCClientError(ethereum.NotFound) return } head.EVMChainID = ubig.New(r.chainID) @@ -515,10 +498,7 @@ func (r *rpcClient) BlockByHash(ctx context.Context, hash common.Hash) (head *ev } func (r *rpcClient) BlockByHashGeth(ctx context.Context, hash common.Hash) (block *types.Block, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("hash", hash) @@ -541,10 +521,7 @@ func (r *rpcClient) BlockByHashGeth(ctx context.Context, hash common.Hash) (bloc } func (r *rpcClient) BlockByNumberGeth(ctx context.Context, number *big.Int) (block *types.Block, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("number", number) @@ -567,15 +544,13 @@ func (r *rpcClient) BlockByNumberGeth(ctx context.Context, number *big.Int) (blo } func (r *rpcClient) SendTransaction(ctx context.Context, tx *types.Transaction) error { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("tx", tx) lggr.Debug("RPC call: evmclient.Client#SendTransaction") start := time.Now() + var err error if http != nil { err = r.wrapHTTP(http.geth.SendTransaction(ctx, tx)) } else { @@ -607,10 +582,7 @@ func (r *rpcClient) SendEmptyTransaction( // PendingSequenceAt returns one higher than the highest nonce from both mempool and mined transactions func (r *rpcClient) PendingSequenceAt(ctx context.Context, account common.Address) (nonce evmtypes.Nonce, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return 0, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("account", account) @@ -639,10 +611,7 @@ func (r *rpcClient) PendingSequenceAt(ctx context.Context, account common.Addres // mined nonce at the given block number, but it actually returns the total // transaction count which is the highest mined nonce + 1 func (r *rpcClient) SequenceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (nonce evmtypes.Nonce, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return 0, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("account", account, "blockNumber", blockNumber) @@ -668,10 +637,7 @@ func (r *rpcClient) SequenceAt(ctx context.Context, account common.Address, bloc } func (r *rpcClient) PendingCodeAt(ctx context.Context, account common.Address) (code []byte, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("account", account) @@ -694,10 +660,7 @@ func (r *rpcClient) PendingCodeAt(ctx context.Context, account common.Address) ( } func (r *rpcClient) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) (code []byte, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("account", account, "blockNumber", blockNumber) @@ -720,10 +683,7 @@ func (r *rpcClient) CodeAt(ctx context.Context, account common.Address, blockNum } func (r *rpcClient) EstimateGas(ctx context.Context, c interface{}) (gas uint64, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return 0, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() call := c.(ethereum.CallMsg) lggr := r.newRqLggr().With("call", call) @@ -747,10 +707,7 @@ func (r *rpcClient) EstimateGas(ctx context.Context, c interface{}) (gas uint64, } func (r *rpcClient) SuggestGasPrice(ctx context.Context) (price *big.Int, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr() @@ -773,10 +730,7 @@ func (r *rpcClient) SuggestGasPrice(ctx context.Context) (price *big.Int, err er } func (r *rpcClient) CallContract(ctx context.Context, msg interface{}, blockNumber *big.Int) (val []byte, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("callMsg", msg, "blockNumber", blockNumber) message := msg.(ethereum.CallMsg) @@ -804,10 +758,7 @@ func (r *rpcClient) CallContract(ctx context.Context, msg interface{}, blockNumb } func (r *rpcClient) PendingCallContract(ctx context.Context, msg interface{}) (val []byte, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("callMsg", msg) message := msg.(ethereum.CallMsg) @@ -841,10 +792,7 @@ func (r *rpcClient) LatestBlockHeight(ctx context.Context) (*big.Int, error) { } func (r *rpcClient) BlockNumber(ctx context.Context) (height uint64, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return 0, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr() @@ -867,10 +815,7 @@ func (r *rpcClient) BlockNumber(ctx context.Context) (height uint64, err error) } func (r *rpcClient) BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (balance *big.Int, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("account", account.Hex(), "blockNumber", blockNumber) @@ -907,7 +852,7 @@ func (r *rpcClient) TokenBalance(ctx context.Context, address common.Address, co return numLinkBigInt, err } if _, ok := numLinkBigInt.SetString(result, 0); !ok { - return nil, fmt.Errorf("failed to parse int: %s", result) + return nil, r.wrapRPCClientError(fmt.Errorf("failed to parse int: %s", result)) } return numLinkBigInt, nil } @@ -926,10 +871,7 @@ func (r *rpcClient) FilterEvents(ctx context.Context, q ethereum.FilterQuery) ([ } func (r *rpcClient) FilterLogs(ctx context.Context, q ethereum.FilterQuery) (l []types.Log, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("q", q) @@ -957,10 +899,7 @@ func (r *rpcClient) ClientVersion(ctx context.Context) (version string, err erro } func (r *rpcClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (sub ethereum.Subscription, err error) { - ctx, cancel, ws, _, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, _ := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr().With("q", q) @@ -968,6 +907,7 @@ func (r *rpcClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQu start := time.Now() sub, err = ws.geth.SubscribeFilterLogs(ctx, q, ch) if err == nil { + sub = newSubscriptionErrorWrapper(sub, r.rpcClientErrorPrefix()) r.registerSub(sub) } err = r.wrapWS(err) @@ -979,10 +919,7 @@ func (r *rpcClient) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQu } func (r *rpcClient) SuggestGasTipCap(ctx context.Context) (tipCap *big.Int, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return nil, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr() @@ -1007,7 +944,7 @@ func (r *rpcClient) SuggestGasTipCap(ctx context.Context) (tipCap *big.Int, err // Returns the ChainID according to the geth client. This is useful for functions like verify() // the common node. func (r *rpcClient) ChainID(ctx context.Context) (chainID *big.Int, err error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() @@ -1026,6 +963,15 @@ func (r *rpcClient) newRqLggr() logger.SugaredLogger { return r.rpcLog.With("requestID", uuid.New()) } +func (r *rpcClient) wrapRPCClientError(err error) error { + // simple add msg to the error without adding new stack trace + return pkgerrors.WithMessage(err, r.rpcClientErrorPrefix()) +} + +func (r *rpcClient) rpcClientErrorPrefix() string { + return fmt.Sprintf("RPCClient returned error (%s)", r.name) +} + func wrapCallError(err error, tp string) error { if err == nil { return nil @@ -1038,11 +984,12 @@ func wrapCallError(err error, tp string) error { func (r *rpcClient) wrapWS(err error) error { err = wrapCallError(err, fmt.Sprintf("%s websocket (%s)", r.tier.String(), r.ws.uri.Redacted())) - return err + return r.wrapRPCClientError(err) } func (r *rpcClient) wrapHTTP(err error) error { err = wrapCallError(err, fmt.Sprintf("%s http (%s)", r.tier.String(), r.http.uri.Redacted())) + err = r.wrapRPCClientError(err) if err != nil { r.rpcLog.Debugw("Call failed", "err", err) } else { @@ -1052,7 +999,7 @@ func (r *rpcClient) wrapHTTP(err error) error { } // makeLiveQueryCtxAndSafeGetClients wraps makeQueryCtx -func (r *rpcClient) makeLiveQueryCtxAndSafeGetClients(parentCtx context.Context) (ctx context.Context, cancel context.CancelFunc, ws rawclient, http *rawclient, err error) { +func (r *rpcClient) makeLiveQueryCtxAndSafeGetClients(parentCtx context.Context) (ctx context.Context, cancel context.CancelFunc, ws rawclient, http *rawclient) { // Need to wrap in mutex because state transition can cancel and replace the // context r.stateMu.RLock() @@ -1072,16 +1019,14 @@ func (r *rpcClient) makeQueryCtx(ctx context.Context) (context.Context, context. } func (r *rpcClient) IsSyncing(ctx context.Context) (bool, error) { - ctx, cancel, ws, http, err := r.makeLiveQueryCtxAndSafeGetClients(ctx) - if err != nil { - return false, err - } + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx) defer cancel() lggr := r.newRqLggr() lggr.Debug("RPC call: evmclient.Client#SyncProgress") var syncProgress *ethereum.SyncProgress start := time.Now() + var err error if http != nil { syncProgress, err = http.geth.SyncProgress(ctx) err = r.wrapHTTP(err) diff --git a/core/chains/evm/client/sub_error_wrapper.go b/core/chains/evm/client/sub_error_wrapper.go new file mode 100644 index 00000000000..689991ce70f --- /dev/null +++ b/core/chains/evm/client/sub_error_wrapper.go @@ -0,0 +1,77 @@ +package client + +import ( + "fmt" + + commontypes "github.com/smartcontractkit/chainlink/v2/common/types" +) + +// subErrorWrapper - adds specified prefix to a subscription error +type subErrorWrapper struct { + sub commontypes.Subscription + errorPrefix string + + done chan struct{} + unSub chan struct{} + errorCh chan error +} + +func newSubscriptionErrorWrapper(sub commontypes.Subscription, errorPrefix string) *subErrorWrapper { + s := &subErrorWrapper{ + sub: sub, + errorPrefix: errorPrefix, + done: make(chan struct{}), + unSub: make(chan struct{}), + errorCh: make(chan error), + } + + go func() { + for { + select { + // sub.Err channel is closed by sub.Unsubscribe + case err, ok := <-sub.Err(): + if !ok { + // might only happen if someone terminated wrapped subscription + // in any case - do our best to release resources + // we can't call Unsubscribe on root sub as this might cause panic + close(s.errorCh) + close(s.done) + return + } + + select { + case s.errorCh <- fmt.Errorf("%s: %w", s.errorPrefix, err): + case <-s.unSub: + s.close() + return + } + case <-s.unSub: + s.close() + return + } + } + }() + + return s +} + +func (s *subErrorWrapper) close() { + s.sub.Unsubscribe() + close(s.errorCh) + close(s.done) +} + +func (s *subErrorWrapper) Unsubscribe() { + select { + // already unsubscribed + case <-s.done: + // signal unsubscribe + case s.unSub <- struct{}{}: + // wait for unsubscribe to complete + <-s.done + } +} + +func (s *subErrorWrapper) Err() <-chan error { + return s.errorCh +} diff --git a/core/chains/evm/client/sub_error_wrapper_test.go b/core/chains/evm/client/sub_error_wrapper_test.go new file mode 100644 index 00000000000..457d392a50e --- /dev/null +++ b/core/chains/evm/client/sub_error_wrapper_test.go @@ -0,0 +1,75 @@ +package client + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" +) + +func TestSubscriptionErrorWrapper(t *testing.T) { + t.Parallel() + t.Run("Unsubscribe wrapper releases resources", func(t *testing.T) { + t.Parallel() + + mockedSub := NewMockSubscription() + const prefix = "RPC returned error" + wrapper := newSubscriptionErrorWrapper(mockedSub, prefix) + wrapper.Unsubscribe() + + // mock's resources were relased + assert.True(t, mockedSub.unsubscribed) + _, ok := <-mockedSub.Err() + assert.False(t, ok) + // wrapper's channels are closed + _, ok = <-wrapper.Err() + assert.False(t, ok) + // subsequence unsubscribe does not causes panic + wrapper.Unsubscribe() + }) + t.Run("Unsubscribe interrupts error delivery", func(t *testing.T) { + t.Parallel() + sub := NewMockSubscription() + const prefix = "RPC returned error" + wrapper := newSubscriptionErrorWrapper(sub, prefix) + sub.Errors <- fmt.Errorf("error") + + wrapper.Unsubscribe() + _, ok := <-wrapper.Err() + assert.False(t, ok) + }) + t.Run("Successfully wraps error", func(t *testing.T) { + t.Parallel() + sub := NewMockSubscription() + const prefix = "RPC returned error" + wrapper := newSubscriptionErrorWrapper(sub, prefix) + sub.Errors <- fmt.Errorf("root error") + + err, ok := <-wrapper.Err() + assert.True(t, ok) + assert.Equal(t, "RPC returned error: root error", err.Error()) + + wrapper.Unsubscribe() + _, ok = <-wrapper.Err() + assert.False(t, ok) + }) + t.Run("Unsubscribe on root does not cause panic", func(t *testing.T) { + t.Parallel() + mockedSub := NewMockSubscription() + wrapper := newSubscriptionErrorWrapper(mockedSub, "") + + mockedSub.Unsubscribe() + // mock's resources were released + assert.True(t, mockedSub.unsubscribed) + _, ok := <-mockedSub.Err() + assert.False(t, ok) + // wrapper's channels are eventually closed + tests.AssertEventually(t, func() bool { + _, ok = <-wrapper.Err() + return !ok + }) + + }) +} diff --git a/core/chains/evm/gas/block_history_estimator.go b/core/chains/evm/gas/block_history_estimator.go index 8b8c626f725..0ae067e45bf 100644 --- a/core/chains/evm/gas/block_history_estimator.go +++ b/core/chains/evm/gas/block_history_estimator.go @@ -721,7 +721,7 @@ func (b *BlockHistoryEstimator) batchFetch(ctx context.Context, reqs []rpc.Batch err := b.ethClient.BatchCallContext(ctx, reqs[i:j]) if pkgerrors.Is(err, context.DeadlineExceeded) { // We ran out of time, return what we have - b.logger.Warnf("Batch fetching timed out; loaded %d/%d results", i, len(reqs)) + b.logger.Warnf("Batch fetching timed out; loaded %d/%d results: %v", i, len(reqs), err) for k := i; k < len(reqs); k++ { if k < j { reqs[k].Error = pkgerrors.Wrap(err, "request failed") From c98ea6413dcdc02a7d0c82b9b36d3fce97dac94b Mon Sep 17 00:00:00 2001 From: Oliver Townsend <133903322+ogtownsend@users.noreply.github.com> Date: Fri, 26 Apr 2024 09:48:56 -0700 Subject: [PATCH 31/34] Update log trigger log provider readMaxBatchSize to 56 (#12951) * Update log provider readMaxBatchSize to 56 * Adding changeset * Add changeset tag --- .changeset/tidy-trees-tie.md | 5 +++++ .../ocr2keeper/evmregistry/v21/logprovider/provider.go | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/tidy-trees-tie.md diff --git a/.changeset/tidy-trees-tie.md b/.changeset/tidy-trees-tie.md new file mode 100644 index 00000000000..7ff415e9de4 --- /dev/null +++ b/.changeset/tidy-trees-tie.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#changed Updating the log trigger log provider's readMaxBatchSize to 56 diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go index b07b08d3354..e2c1a1531e2 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go @@ -42,7 +42,7 @@ var ( readJobQueueSize = 64 readLogsTimeout = 10 * time.Second - readMaxBatchSize = 32 + readMaxBatchSize = 56 // reorgBuffer is the number of blocks to add as a buffer to the block range when reading logs. reorgBuffer = int64(32) readerThreads = 4 From 7338448469d014b4b1eb5aaedf0303f687e45f62 Mon Sep 17 00:00:00 2001 From: Dylan Tinianov Date: Fri, 26 Apr 2024 13:10:57 -0400 Subject: [PATCH 32/34] Create HeadPoller for Multi-Node (#12871) * Create polling transformer * Update poller * Rename to HeadPoller * lint * update poller * Update head poller * Update poller * lint * Refactor Poller * Update poller_test.go * Update poller * Synchronize tests * Refactor with timeout * Check test logs * Update Poller * Update poller_test.go * Update poller_test.go * Simplify poller * Set logging to warn --- common/client/poller.go | 98 +++++++++++++++++ common/client/poller_test.go | 207 +++++++++++++++++++++++++++++++++++ 2 files changed, 305 insertions(+) create mode 100644 common/client/poller.go create mode 100644 common/client/poller_test.go diff --git a/common/client/poller.go b/common/client/poller.go new file mode 100644 index 00000000000..b21f28fe604 --- /dev/null +++ b/common/client/poller.go @@ -0,0 +1,98 @@ +package client + +import ( + "context" + "sync" + "time" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + + "github.com/smartcontractkit/chainlink/v2/common/types" +) + +// Poller is a component that polls a function at a given interval +// and delivers the result to a channel. It is used by multinode to poll +// for new heads and implements the Subscription interface. +type Poller[T any] struct { + services.StateMachine + pollingInterval time.Duration + pollingFunc func(ctx context.Context) (T, error) + pollingTimeout time.Duration + logger logger.Logger + channel chan<- T + errCh chan error + + stopCh services.StopChan + wg sync.WaitGroup +} + +// NewPoller creates a new Poller instance +func NewPoller[ + T any, +](pollingInterval time.Duration, pollingFunc func(ctx context.Context) (T, error), pollingTimeout time.Duration, channel chan<- T, logger logger.Logger) Poller[T] { + return Poller[T]{ + pollingInterval: pollingInterval, + pollingFunc: pollingFunc, + pollingTimeout: pollingTimeout, + channel: channel, + logger: logger, + errCh: make(chan error), + stopCh: make(chan struct{}), + } +} + +var _ types.Subscription = &Poller[any]{} + +func (p *Poller[T]) Start() error { + return p.StartOnce("Poller", func() error { + p.wg.Add(1) + go p.pollingLoop() + return nil + }) +} + +// Unsubscribe cancels the sending of events to the data channel +func (p *Poller[T]) Unsubscribe() { + _ = p.StopOnce("Poller", func() error { + close(p.stopCh) + p.wg.Wait() + close(p.errCh) + return nil + }) +} + +func (p *Poller[T]) Err() <-chan error { + return p.errCh +} + +func (p *Poller[T]) pollingLoop() { + defer p.wg.Done() + + ticker := time.NewTicker(p.pollingInterval) + defer ticker.Stop() + + for { + select { + case <-p.stopCh: + return + case <-ticker.C: + // Set polling timeout + pollingCtx, cancelPolling := context.WithTimeout(context.Background(), p.pollingTimeout) + p.stopCh.CtxCancel(pollingCtx, cancelPolling) + // Execute polling function + result, err := p.pollingFunc(pollingCtx) + cancelPolling() + if err != nil { + p.logger.Warnf("polling error: %v", err) + continue + } + // Send result to channel or block if channel is full + select { + case p.channel <- result: + case <-p.stopCh: + return + } + } + } +} diff --git a/common/client/poller_test.go b/common/client/poller_test.go new file mode 100644 index 00000000000..3f11c759adb --- /dev/null +++ b/common/client/poller_test.go @@ -0,0 +1,207 @@ +package client + +import ( + "context" + "fmt" + "math/big" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" +) + +func Test_Poller(t *testing.T) { + lggr := logger.Test(t) + + t.Run("Test multiple start", func(t *testing.T) { + pollFunc := func(ctx context.Context) (Head, error) { + return nil, nil + } + + channel := make(chan Head, 1) + defer close(channel) + + poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, lggr) + err := poller.Start() + require.NoError(t, err) + + err = poller.Start() + require.Error(t, err) + poller.Unsubscribe() + }) + + t.Run("Test polling for heads", func(t *testing.T) { + // Mock polling function that returns a new value every time it's called + var pollNumber int + pollLock := sync.Mutex{} + pollFunc := func(ctx context.Context) (Head, error) { + pollLock.Lock() + defer pollLock.Unlock() + pollNumber++ + h := head{ + BlockNumber: int64(pollNumber), + BlockDifficulty: big.NewInt(int64(pollNumber)), + } + return h.ToMockHead(t), nil + } + + // data channel to receive updates from the poller + channel := make(chan Head, 1) + defer close(channel) + + // Create poller and start to receive data + poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, lggr) + require.NoError(t, poller.Start()) + defer poller.Unsubscribe() + + // Receive updates from the poller + pollCount := 0 + pollMax := 50 + for ; pollCount < pollMax; pollCount++ { + h := <-channel + assert.Equal(t, int64(pollCount+1), h.BlockNumber()) + } + }) + + t.Run("Test polling errors", func(t *testing.T) { + // Mock polling function that returns an error + var pollNumber int + pollLock := sync.Mutex{} + pollFunc := func(ctx context.Context) (Head, error) { + pollLock.Lock() + defer pollLock.Unlock() + pollNumber++ + return nil, fmt.Errorf("polling error %d", pollNumber) + } + + // data channel to receive updates from the poller + channel := make(chan Head, 1) + defer close(channel) + + olggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) + + // Create poller and subscribe to receive data + poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, olggr) + require.NoError(t, poller.Start()) + defer poller.Unsubscribe() + + // Ensure that all errors were logged as expected + logsSeen := func() bool { + for pollCount := 0; pollCount < 50; pollCount++ { + numLogs := observedLogs.FilterMessage(fmt.Sprintf("polling error: polling error %d", pollCount+1)).Len() + if numLogs != 1 { + return false + } + } + return true + } + require.Eventually(t, logsSeen, time.Second, time.Millisecond) + }) + + t.Run("Test polling timeout", func(t *testing.T) { + pollFunc := func(ctx context.Context) (Head, error) { + if <-ctx.Done(); true { + return nil, ctx.Err() + } + return nil, nil + } + + // Set instant timeout + pollingTimeout := time.Duration(0) + + // data channel to receive updates from the poller + channel := make(chan Head, 1) + defer close(channel) + + olggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) + + // Create poller and subscribe to receive data + poller := NewPoller[Head](time.Millisecond, pollFunc, pollingTimeout, channel, olggr) + require.NoError(t, poller.Start()) + defer poller.Unsubscribe() + + // Ensure that timeout errors were logged as expected + logsSeen := func() bool { + return observedLogs.FilterMessage("polling error: context deadline exceeded").Len() >= 1 + } + require.Eventually(t, logsSeen, time.Second, time.Millisecond) + }) + + t.Run("Test unsubscribe during polling", func(t *testing.T) { + wait := make(chan struct{}) + pollFunc := func(ctx context.Context) (Head, error) { + close(wait) + // Block in polling function until context is cancelled + if <-ctx.Done(); true { + return nil, ctx.Err() + } + return nil, nil + } + + // Set long timeout + pollingTimeout := time.Minute + + // data channel to receive updates from the poller + channel := make(chan Head, 1) + defer close(channel) + + olggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) + + // Create poller and subscribe to receive data + poller := NewPoller[Head](time.Millisecond, pollFunc, pollingTimeout, channel, olggr) + require.NoError(t, poller.Start()) + + // Unsubscribe while blocked in polling function + <-wait + poller.Unsubscribe() + + // Ensure error was logged + logsSeen := func() bool { + return observedLogs.FilterMessage("polling error: context canceled").Len() >= 1 + } + require.Eventually(t, logsSeen, time.Second, time.Millisecond) + }) +} + +func Test_Poller_Unsubscribe(t *testing.T) { + lggr := logger.Test(t) + pollFunc := func(ctx context.Context) (Head, error) { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + h := head{ + BlockNumber: 0, + BlockDifficulty: big.NewInt(0), + } + return h.ToMockHead(t), nil + } + } + + t.Run("Test multiple unsubscribe", func(t *testing.T) { + channel := make(chan Head, 1) + poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, lggr) + err := poller.Start() + require.NoError(t, err) + + <-channel + poller.Unsubscribe() + poller.Unsubscribe() + }) + + t.Run("Test unsubscribe with closed channel", func(t *testing.T) { + channel := make(chan Head, 1) + poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, lggr) + err := poller.Start() + require.NoError(t, err) + + <-channel + close(channel) + poller.Unsubscribe() + }) +} From 2e994684de6d326ff3dc4674986a10fbf28e3511 Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Sat, 27 Apr 2024 13:04:49 -0400 Subject: [PATCH 33/34] Remove codecov (#13020) --- codecov.yml | 15 - tools/bin/codecov | 1888 --------------------------------------- tools/bin/go_core_tests | 2 - 3 files changed, 1905 deletions(-) delete mode 100644 codecov.yml delete mode 100755 tools/bin/codecov diff --git a/codecov.yml b/codecov.yml deleted file mode 100644 index a70f1961e36..00000000000 --- a/codecov.yml +++ /dev/null @@ -1,15 +0,0 @@ -comment: false - -coverage: - status: - project: - default: - threshold: 1% - -github_checks: - annotations: false - -ignore: - - 'contracts/' # Disabled due to solidity-coverage not reporting coverage - - 'core/internal' - - 'core/scripts' diff --git a/tools/bin/codecov b/tools/bin/codecov deleted file mode 100755 index 36513ce06df..00000000000 --- a/tools/bin/codecov +++ /dev/null @@ -1,1888 +0,0 @@ -#!/usr/bin/env bash - -# Apache License Version 2.0, January 2004 -# https://github.com/codecov/codecov-bash/blob/master/LICENSE - -set -e +o pipefail - -VERSION="1.0.6" - -codecov_flags=( ) -url="https://codecov.io" -env="$CODECOV_ENV" -service="" -token="" -search_in="" -# shellcheck disable=SC2153 -flags="$CODECOV_FLAGS" -exit_with=0 -curlargs="" -curlawsargs="" -dump="0" -clean="0" -curl_s="-s" -name="$CODECOV_NAME" -include_cov="" -exclude_cov="" -ddp="$HOME/Library/Developer/Xcode/DerivedData" -xp="" -files="" -save_to="" -direct_file_upload="" -cacert="$CODECOV_CA_BUNDLE" -gcov_ignore="-not -path './bower_components/**' -not -path './node_modules/**' -not -path './vendor/**'" -gcov_include="" - -ft_gcov="1" -ft_coveragepy="1" -ft_fix="1" -ft_search="1" -ft_s3="1" -ft_network="1" -ft_xcodellvm="1" -ft_xcodeplist="0" -ft_gcovout="1" -ft_html="0" -ft_yaml="0" - -_git_root=$(git rev-parse --show-toplevel 2>/dev/null || hg root 2>/dev/null || echo "$PWD") -git_root="$_git_root" -remote_addr="" -if [ "$git_root" = "$PWD" ]; -then - git_root="." -fi - -branch_o="" -build_o="" -commit_o="" -pr_o="" -prefix_o="" -network_filter_o="" -search_in_o="" -slug_o="" -tag_o="" -url_o="" -git_ls_files_recurse_submodules_o="" -package="bash" - -commit="$VCS_COMMIT_ID" -branch="$VCS_BRANCH_NAME" -pr="$VCS_PULL_REQUEST" -slug="$VCS_SLUG" -tag="$VCS_TAG" -build_url="$CI_BUILD_URL" -build="$CI_BUILD_ID" -job="$CI_JOB_ID" - -beta_xcode_partials="" - -proj_root="$git_root" -gcov_exe="gcov" -gcov_arg="" - -b="\033[0;36m" -g="\033[0;32m" -r="\033[0;31m" -e="\033[0;90m" -y="\033[0;33m" -x="\033[0m" - -show_help() { -cat << EOF - - Codecov Bash $VERSION - - Global report uploading tool for Codecov - Documentation at https://docs.codecov.io/docs - Contribute at https://github.com/codecov/codecov-bash - - - -h Display this help and exit - -f FILE Target file(s) to upload - - -f "path/to/file" only upload this file - skips searching unless provided patterns below - - -f '!*.bar' ignore all files at pattern *.bar - -f '*.foo' include all files at pattern *.foo - Must use single quotes. - This is non-exclusive, use -s "*.foo" to match specific paths. - - -s DIR Directory to search for coverage reports. - Already searches project root and artifact folders. - -t TOKEN Set the private repository token - (option) set environment variable CODECOV_TOKEN=:uuid - - -t @/path/to/token_file - -t uuid - - -n NAME Custom defined name of the upload. Visible in Codecov UI - - -e ENV Specify environment variables to be included with this build - Also accepting environment variables: CODECOV_ENV=VAR,VAR2 - - -e VAR,VAR2 - - -k prefix Prefix filepaths to help resolve path fixing - - -i prefix Only include files in the network with a certain prefix. Useful for upload-specific path fixing - - -X feature Toggle functionalities - - -X gcov Disable gcov - -X coveragepy Disable python coverage - -X fix Disable report fixing - -X search Disable searching for reports - -X xcode Disable xcode processing - -X network Disable uploading the file network - -X gcovout Disable gcov output - -X html Enable coverage for HTML files - -X recursesubs Enable recurse submodules in git projects when searching for source files - -X yaml Enable coverage for YAML files - - -N The commit SHA of the parent for which you are uploading coverage. If not present, - the parent will be determined using the API of your repository provider. - When using the repository provider's API, the parent is determined via finding - the closest ancestor to the commit. - - -R root dir Used when not in git/hg project to identify project root directory - -F flag Flag the upload to group coverage metrics - - -F unittests This upload is only unittests - -F integration This upload is only integration tests - -F ui,chrome This upload is Chrome - UI tests - - -c Move discovered coverage reports to the trash - -z FILE Upload specified file directly to Codecov and bypass all report generation. - This is inteded to be used only with a pre-formatted Codecov report and is not - expected to work under any other circumstances. - -Z Exit with 1 if not successful. Default will Exit with 0 - - -- xcode -- - -D Custom Derived Data Path for Coverage.profdata and gcov processing - Default '~/Library/Developer/Xcode/DerivedData' - -J Specify packages to build coverage. Uploader will only build these packages. - This can significantly reduces time to build coverage reports. - - -J 'MyAppName' Will match "MyAppName" and "MyAppNameTests" - -J '^ExampleApp$' Will match only "ExampleApp" not "ExampleAppTests" - - -- gcov -- - -g GLOB Paths to ignore during gcov gathering - -G GLOB Paths to include during gcov gathering - -p dir Project root directory - Also used when preparing gcov - -x gcovexe gcov executable to run. Defaults to 'gcov' - -a gcovargs extra arguments to pass to gcov - - -- Override CI Environment Variables -- - These variables are automatically detected by popular CI providers - - -B branch Specify the branch name - -C sha Specify the commit sha - -P pr Specify the pull request number - -b build Specify the build number - -T tag Specify the git tag - - -- Enterprise -- - -u URL Set the target url for Enterprise customers - Not required when retrieving the bash uploader from your CCE - (option) Set environment variable CODECOV_URL=https://my-hosted-codecov.com - -r SLUG owner/repo slug used instead of the private repo token in Enterprise - (option) set environment variable CODECOV_SLUG=:owner/:repo - (option) set in your codecov.yml "codecov.slug" - -S PATH File path to your cacert.pem file used to verify ssl with Codecov Enterprise (optional) - (option) Set environment variable: CODECOV_CA_BUNDLE="/path/to/ca.pem" - -U curlargs Extra curl arguments to communicate with Codecov. e.g., -U "--proxy http://http-proxy" - -A curlargs Extra curl arguments to communicate with AWS. - - -- Debugging -- - -d Don't upload, but dump upload file to stdout - -q PATH Write upload file to path - -K Remove color from the output - -v Verbose mode - -EOF -} - - -say() { - echo -e "$1" -} - - -urlencode() { - echo "$1" | curl -Gso /dev/null -w "%{url_effective}" --data-urlencode @- "" | cut -c 3- | sed -e 's/%0A//' -} - -swiftcov() { - _dir=$(dirname "$1" | sed 's/\(Build\).*/\1/g') - for _type in app framework xctest - do - find "$_dir" -name "*.$_type" | while read -r f - do - _proj=${f##*/} - _proj=${_proj%."$_type"} - if [ "$2" = "" ] || [ "$(echo "$_proj" | grep -i "$2")" != "" ]; - then - say " $g+$x Building reports for $_proj $_type" - dest=$([ -f "$f/$_proj" ] && echo "$f/$_proj" || echo "$f/Contents/MacOS/$_proj") - # shellcheck disable=SC2001 - _proj_name=$(echo "$_proj" | sed -e 's/[[:space:]]//g') - # shellcheck disable=SC2086 - xcrun llvm-cov show $beta_xcode_partials -instr-profile "$1" "$dest" > "$_proj_name.$_type.coverage.txt" \ - || say " ${r}x>${x} llvm-cov failed to produce results for $dest" - fi - done - done -} - - -# Credits to: https://gist.github.com/pkuczynski/8665367 -parse_yaml() { - local prefix=$2 - local s='[[:space:]]*' w='[a-zA-Z0-9_]*' - local fs - fs=$(echo @|tr @ '\034') - sed -ne "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \ - -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" "$1" | - awk -F"$fs" '{ - indent = length($1)/2; - vname[indent] = $2; - for (i in vname) {if (i > indent) {delete vname[i]}} - if (length($3) > 0) { - vn=""; if (indent > 0) {vn=(vn)(vname[0])("_")} - printf("%s%s%s=\"%s\"\n", "'"$prefix"'",vn, $2, $3); - } - }' -} - -if [ $# != 0 ]; -then - while getopts "a:A:b:B:cC:dD:e:f:F:g:G:hi:J:k:Kn:p:P:Q:q:r:R:s:S:t:T:u:U:vx:X:Zz:N:-" o - do - codecov_flags+=( "$o" ) - case "$o" in - "-") - echo -e "${r}Long options are not supported${x}" - exit 2 - ;; - "?") - ;; - "N") - parent=$OPTARG - ;; - "a") - gcov_arg=$OPTARG - ;; - "A") - curlawsargs="$OPTARG" - ;; - "b") - build_o="$OPTARG" - ;; - "B") - branch_o="$OPTARG" - ;; - "c") - clean="1" - ;; - "C") - commit_o="$OPTARG" - ;; - "d") - dump="1" - ;; - "D") - ddp="$OPTARG" - ;; - "e") - env="$env,$OPTARG" - ;; - "f") - if [ "${OPTARG::1}" = "!" ]; - then - exclude_cov="$exclude_cov -not -path '${OPTARG:1}'" - - elif [[ "$OPTARG" = *"*"* ]]; - then - include_cov="$include_cov -or -path '$OPTARG'" - - else - ft_search=0 - if [ "$files" = "" ]; - then - files="$OPTARG" - else - files="$files -$OPTARG" - fi - fi - ;; - "F") - if [ "$flags" = "" ]; - then - flags="$OPTARG" - else - flags="$flags,$OPTARG" - fi - ;; - "g") - gcov_ignore="$gcov_ignore -not -path '$OPTARG'" - ;; - "G") - gcov_include="$gcov_include -path '$OPTARG'" - ;; - "h") - show_help - exit 0; - ;; - "i") - network_filter_o="$OPTARG" - ;; - "J") - ft_xcodellvm="1" - ft_xcodeplist="0" - if [ "$xp" = "" ]; - then - xp="$OPTARG" - else - xp="$xp\|$OPTARG" - fi - ;; - "k") - prefix_o=$(echo "$OPTARG" | sed -e 's:^/*::' -e 's:/*$::') - ;; - "K") - b="" - g="" - r="" - e="" - x="" - ;; - "n") - name="$OPTARG" - ;; - "p") - proj_root="$OPTARG" - ;; - "P") - pr_o="$OPTARG" - ;; - "Q") - # this is only meant for Codecov packages to overwrite - package="$OPTARG" - ;; - "q") - save_to="$OPTARG" - ;; - "r") - slug_o="$OPTARG" - ;; - "R") - git_root="$OPTARG" - ;; - "s") - if [ "$search_in_o" = "" ]; - then - search_in_o="$OPTARG" - else - search_in_o="$search_in_o $OPTARG" - fi - ;; - "S") - # shellcheck disable=SC2089 - cacert="--cacert \"$OPTARG\"" - ;; - "t") - if [ "${OPTARG::1}" = "@" ]; - then - token=$(< "${OPTARG:1}" tr -d ' \n') - else - token="$OPTARG" - fi - ;; - "T") - tag_o="$OPTARG" - ;; - "u") - url_o=$(echo "$OPTARG" | sed -e 's/\/$//') - ;; - "U") - curlargs="$OPTARG" - ;; - "v") - set -x - curl_s="" - ;; - "x") - gcov_exe=$OPTARG - ;; - "X") - if [ "$OPTARG" = "gcov" ]; - then - ft_gcov="0" - elif [ "$OPTARG" = "coveragepy" ] || [ "$OPTARG" = "py" ]; - then - ft_coveragepy="0" - elif [ "$OPTARG" = "gcovout" ]; - then - ft_gcovout="0" - elif [ "$OPTARG" = "xcodellvm" ]; - then - ft_xcodellvm="1" - ft_xcodeplist="0" - elif [ "$OPTARG" = "fix" ] || [ "$OPTARG" = "fixes" ]; - then - ft_fix="0" - elif [ "$OPTARG" = "xcode" ]; - then - ft_xcodellvm="0" - ft_xcodeplist="0" - elif [ "$OPTARG" = "search" ]; - then - ft_search="0" - elif [ "$OPTARG" = "xcodepartials" ]; - then - beta_xcode_partials="-use-color" - elif [ "$OPTARG" = "network" ]; - then - ft_network="0" - elif [ "$OPTARG" = "s3" ]; - then - ft_s3="0" - elif [ "$OPTARG" = "html" ]; - then - ft_html="1" - elif [ "$OPTARG" = "recursesubs" ]; - then - git_ls_files_recurse_submodules_o="--recurse-submodules" - elif [ "$OPTARG" = "yaml" ]; - then - ft_yaml="1" - fi - ;; - "Z") - exit_with=1 - ;; - "z") - direct_file_upload="$OPTARG" - ft_gcov="0" - ft_coveragepy="0" - ft_fix="0" - ft_search="0" - ft_network="0" - ft_xcodellvm="0" - ft_gcovout="0" - include_cov="" - ;; - *) - echo -e "${r}Unexpected flag not supported${x}" - ;; - esac - done -fi - -say " - _____ _ - / ____| | | -| | ___ __| | ___ ___ _____ __ -| | / _ \\ / _\` |/ _ \\/ __/ _ \\ \\ / / -| |___| (_) | (_| | __/ (_| (_) \\ V / - \\_____\\___/ \\__,_|\\___|\\___\\___/ \\_/ - Bash-$VERSION - -" - -# check for installed tools -# git/hg -if [ "$direct_file_upload" = "" ]; -then - if [ -x "$(command -v git)" ]; - then - say "$b==>$x $(git --version) found" - else - say "$y==>$x git not installed, testing for mercurial" - if [ -x "$(command -v hg)" ]; - then - say "$b==>$x $(hg --version) found" - else - say "$r==>$x git nor mercurial are installed. Uploader may fail or have unintended consequences" - fi - fi -fi -# curl -if [ -x "$(command -v curl)" ]; -then - say "$b==>$x $(curl --version)" -else - say "$r==>$x curl not installed. Exiting." - exit ${exit_with}; -fi - -search_in="$proj_root" - -#shellcheck disable=SC2154 -if [ "$JENKINS_URL" != "" ]; -then - say "$e==>$x Jenkins CI detected." - # https://wiki.jenkins-ci.org/display/JENKINS/Building+a+software+project - # https://wiki.jenkins-ci.org/display/JENKINS/GitHub+pull+request+builder+plugin#GitHubpullrequestbuilderplugin-EnvironmentVariables - service="jenkins" - - # shellcheck disable=SC2154 - if [ "$ghprbSourceBranch" != "" ]; - then - branch="$ghprbSourceBranch" - elif [ "$GIT_BRANCH" != "" ]; - then - branch="$GIT_BRANCH" - elif [ "$BRANCH_NAME" != "" ]; - then - branch="$BRANCH_NAME" - fi - - # shellcheck disable=SC2154 - if [ "$ghprbActualCommit" != "" ]; - then - commit="$ghprbActualCommit" - elif [ "$GIT_COMMIT" != "" ]; - then - commit="$GIT_COMMIT" - fi - - # shellcheck disable=SC2154 - if [ "$ghprbPullId" != "" ]; - then - pr="$ghprbPullId" - elif [ "$CHANGE_ID" != "" ]; - then - pr="$CHANGE_ID" - fi - - build="$BUILD_NUMBER" - # shellcheck disable=SC2153 - build_url=$(urlencode "$BUILD_URL") - -elif [ "$CI" = "true" ] && [ "$TRAVIS" = "true" ] && [ "$SHIPPABLE" != "true" ]; -then - say "$e==>$x Travis CI detected." - # https://docs.travis-ci.com/user/environment-variables/ - service="travis" - commit="${TRAVIS_PULL_REQUEST_SHA:-$TRAVIS_COMMIT}" - build="$TRAVIS_JOB_NUMBER" - pr="$TRAVIS_PULL_REQUEST" - job="$TRAVIS_JOB_ID" - slug="$TRAVIS_REPO_SLUG" - env="$env,TRAVIS_OS_NAME" - tag="$TRAVIS_TAG" - if [ "$TRAVIS_BRANCH" != "$TRAVIS_TAG" ]; - then - branch="${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH}" - fi - - language=$(compgen -A variable | grep "^TRAVIS_.*_VERSION$" | head -1) - if [ "$language" != "" ]; - then - env="$env,${!language}" - fi - -elif [ "$CODEBUILD_CI" = "true" ]; -then - say "$e==>$x AWS Codebuild detected." - # https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html - service="codebuild" - commit="$CODEBUILD_RESOLVED_SOURCE_VERSION" - build="$CODEBUILD_BUILD_ID" - branch="$(echo "$CODEBUILD_WEBHOOK_HEAD_REF" | sed 's/^refs\/heads\///')" - if [ "${CODEBUILD_SOURCE_VERSION/pr}" = "$CODEBUILD_SOURCE_VERSION" ] ; then - pr="false" - else - pr="$(echo "$CODEBUILD_SOURCE_VERSION" | sed 's/^pr\///')" - fi - job="$CODEBUILD_BUILD_ID" - slug="$(echo "$CODEBUILD_SOURCE_REPO_URL" | sed 's/^.*:\/\/[^\/]*\///' | sed 's/\.git$//')" - -elif [ "$CI" = "true" ] && [ "$CI_NAME" = "codeship" ]; -then - say "$e==>$x Codeship CI detected." - # https://www.codeship.io/documentation/continuous-integration/set-environment-variables/ - service="codeship" - branch="$CI_BRANCH" - build="$CI_BUILD_NUMBER" - build_url=$(urlencode "$CI_BUILD_URL") - commit="$CI_COMMIT_ID" - -elif [ -n "$CF_BUILD_URL" ] && [ -n "$CF_BUILD_ID" ]; -then - say "$e==>$x Codefresh CI detected." - # https://docs.codefresh.io/v1.0/docs/variables - service="codefresh" - branch="$CF_BRANCH" - build="$CF_BUILD_ID" - build_url=$(urlencode "$CF_BUILD_URL") - commit="$CF_REVISION" - -elif [ "$TEAMCITY_VERSION" != "" ]; -then - say "$e==>$x TeamCity CI detected." - # https://confluence.jetbrains.com/display/TCD8/Predefined+Build+Parameters - # https://confluence.jetbrains.com/plugins/servlet/mobile#content/view/74847298 - if [ "$TEAMCITY_BUILD_BRANCH" = '' ]; - then - echo " Teamcity does not automatically make build parameters available as environment variables." - echo " Add the following environment parameters to the build configuration" - echo " env.TEAMCITY_BUILD_BRANCH = %teamcity.build.branch%" - echo " env.TEAMCITY_BUILD_ID = %teamcity.build.id%" - echo " env.TEAMCITY_BUILD_URL = %teamcity.serverUrl%/viewLog.html?buildId=%teamcity.build.id%" - echo " env.TEAMCITY_BUILD_COMMIT = %system.build.vcs.number%" - echo " env.TEAMCITY_BUILD_REPOSITORY = %vcsroot..url%" - fi - service="teamcity" - branch="$TEAMCITY_BUILD_BRANCH" - build="$TEAMCITY_BUILD_ID" - build_url=$(urlencode "$TEAMCITY_BUILD_URL") - if [ "$TEAMCITY_BUILD_COMMIT" != "" ]; - then - commit="$TEAMCITY_BUILD_COMMIT" - else - commit="$BUILD_VCS_NUMBER" - fi - remote_addr="$TEAMCITY_BUILD_REPOSITORY" - -elif [ "$CI" = "true" ] && [ "$CIRCLECI" = "true" ]; -then - say "$e==>$x Circle CI detected." - # https://circleci.com/docs/environment-variables - service="circleci" - branch="$CIRCLE_BRANCH" - build="$CIRCLE_BUILD_NUM" - job="$CIRCLE_NODE_INDEX" - if [ "$CIRCLE_PROJECT_REPONAME" != "" ]; - then - slug="$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME" - else - # git@github.com:owner/repo.git - slug="${CIRCLE_REPOSITORY_URL##*:}" - # owner/repo.git - slug="${slug%%.git}" - fi - pr="${CIRCLE_PULL_REQUEST##*/}" - commit="$CIRCLE_SHA1" - search_in="$search_in $CIRCLE_ARTIFACTS $CIRCLE_TEST_REPORTS" - -elif [ "$BUDDYBUILD_BRANCH" != "" ]; -then - say "$e==>$x buddybuild detected" - # http://docs.buddybuild.com/v6/docs/custom-prebuild-and-postbuild-steps - service="buddybuild" - branch="$BUDDYBUILD_BRANCH" - build="$BUDDYBUILD_BUILD_NUMBER" - build_url="https://dashboard.buddybuild.com/public/apps/$BUDDYBUILD_APP_ID/build/$BUDDYBUILD_BUILD_ID" - # BUDDYBUILD_TRIGGERED_BY - if [ "$ddp" = "$HOME/Library/Developer/Xcode/DerivedData" ]; - then - ddp="/private/tmp/sandbox/${BUDDYBUILD_APP_ID}/bbtest" - fi - -elif [ "${bamboo_planRepository_revision}" != "" ]; -then - say "$e==>$x Bamboo detected" - # https://confluence.atlassian.com/bamboo/bamboo-variables-289277087.html#Bamboovariables-Build-specificvariables - service="bamboo" - commit="${bamboo_planRepository_revision}" - # shellcheck disable=SC2154 - branch="${bamboo_planRepository_branch}" - # shellcheck disable=SC2154 - build="${bamboo_buildNumber}" - # shellcheck disable=SC2154 - build_url="${bamboo_buildResultsUrl}" - # shellcheck disable=SC2154 - remote_addr="${bamboo_planRepository_repositoryUrl}" - -elif [ "$CI" = "true" ] && [ "$BITRISE_IO" = "true" ]; -then - # http://devcenter.bitrise.io/faq/available-environment-variables/ - say "$e==>$x Bitrise CI detected." - service="bitrise" - branch="$BITRISE_GIT_BRANCH" - build="$BITRISE_BUILD_NUMBER" - build_url=$(urlencode "$BITRISE_BUILD_URL") - pr="$BITRISE_PULL_REQUEST" - if [ "$GIT_CLONE_COMMIT_HASH" != "" ]; - then - commit="$GIT_CLONE_COMMIT_HASH" - fi - -elif [ "$CI" = "true" ] && [ "$SEMAPHORE" = "true" ]; -then - say "$e==>$x Semaphore CI detected." -# https://docs.semaphoreci.com/ci-cd-environment/environment-variables/#semaphore-related - service="semaphore" - branch="$SEMAPHORE_GIT_BRANCH" - build="$SEMAPHORE_WORKFLOW_NUMBER" - job="$SEMAPHORE_JOB_ID" - pr="$PULL_REQUEST_NUMBER" - slug="$SEMAPHORE_REPO_SLUG" - commit="$REVISION" - env="$env,SEMAPHORE_TRIGGER_SOURCE" - -elif [ "$CI" = "true" ] && [ "$BUILDKITE" = "true" ]; -then - say "$e==>$x Buildkite CI detected." - # https://buildkite.com/docs/guides/environment-variables - service="buildkite" - branch="$BUILDKITE_BRANCH" - build="$BUILDKITE_BUILD_NUMBER" - job="$BUILDKITE_JOB_ID" - build_url=$(urlencode "$BUILDKITE_BUILD_URL") - slug="$BUILDKITE_PROJECT_SLUG" - commit="$BUILDKITE_COMMIT" - if [[ "$BUILDKITE_PULL_REQUEST" != "false" ]]; then - pr="$BUILDKITE_PULL_REQUEST" - fi - tag="$BUILDKITE_TAG" - -elif [ "$CI" = "drone" ] || [ "$DRONE" = "true" ]; -then - say "$e==>$x Drone CI detected." - # http://docs.drone.io/env.html - # drone commits are not full shas - service="drone.io" - branch="$DRONE_BRANCH" - build="$DRONE_BUILD_NUMBER" - build_url=$(urlencode "${DRONE_BUILD_LINK}") - pr="$DRONE_PULL_REQUEST" - job="$DRONE_JOB_NUMBER" - tag="$DRONE_TAG" - -elif [ "$CI" = "true" ] && [ "$HEROKU_TEST_RUN_BRANCH" != "" ]; -then - say "$e==>$x Heroku CI detected." - # https://devcenter.heroku.com/articles/heroku-ci#environment-variables - service="heroku" - branch="$HEROKU_TEST_RUN_BRANCH" - build="$HEROKU_TEST_RUN_ID" - commit="$HEROKU_TEST_RUN_COMMIT_VERSION" - -elif [[ "$CI" = "true" || "$CI" = "True" ]] && [[ "$APPVEYOR" = "true" || "$APPVEYOR" = "True" ]]; -then - say "$e==>$x Appveyor CI detected." - # http://www.appveyor.com/docs/environment-variables - service="appveyor" - branch="$APPVEYOR_REPO_BRANCH" - build=$(urlencode "$APPVEYOR_JOB_ID") - pr="$APPVEYOR_PULL_REQUEST_NUMBER" - job="$APPVEYOR_ACCOUNT_NAME%2F$APPVEYOR_PROJECT_SLUG%2F$APPVEYOR_BUILD_VERSION" - slug="$APPVEYOR_REPO_NAME" - commit="$APPVEYOR_REPO_COMMIT" - build_url=$(urlencode "${APPVEYOR_URL}/project/${APPVEYOR_REPO_NAME}/builds/$APPVEYOR_BUILD_ID/job/${APPVEYOR_JOB_ID}") - -elif [ "$CI" = "true" ] && [ "$WERCKER_GIT_BRANCH" != "" ]; -then - say "$e==>$x Wercker CI detected." - # http://devcenter.wercker.com/articles/steps/variables.html - service="wercker" - branch="$WERCKER_GIT_BRANCH" - build="$WERCKER_MAIN_PIPELINE_STARTED" - slug="$WERCKER_GIT_OWNER/$WERCKER_GIT_REPOSITORY" - commit="$WERCKER_GIT_COMMIT" - -elif [ "$CI" = "true" ] && [ "$MAGNUM" = "true" ]; -then - say "$e==>$x Magnum CI detected." - # https://magnum-ci.com/docs/environment - service="magnum" - branch="$CI_BRANCH" - build="$CI_BUILD_NUMBER" - commit="$CI_COMMIT" - -elif [ "$SHIPPABLE" = "true" ]; -then - say "$e==>$x Shippable CI detected." - # http://docs.shippable.com/ci_configure/ - service="shippable" - # shellcheck disable=SC2153 - branch=$([ "$HEAD_BRANCH" != "" ] && echo "$HEAD_BRANCH" || echo "$BRANCH") - build="$BUILD_NUMBER" - build_url=$(urlencode "$BUILD_URL") - pr="$PULL_REQUEST" - slug="$REPO_FULL_NAME" - # shellcheck disable=SC2153 - commit="$COMMIT" - -elif [ "$TDDIUM" = "true" ]; -then - say "Solano CI detected." - # http://docs.solanolabs.com/Setup/tddium-set-environment-variables/ - service="solano" - commit="$TDDIUM_CURRENT_COMMIT" - branch="$TDDIUM_CURRENT_BRANCH" - build="$TDDIUM_TID" - pr="$TDDIUM_PR_ID" - -elif [ "$GREENHOUSE" = "true" ]; -then - say "$e==>$x Greenhouse CI detected." - # http://docs.greenhouseci.com/docs/environment-variables-files - service="greenhouse" - branch="$GREENHOUSE_BRANCH" - build="$GREENHOUSE_BUILD_NUMBER" - build_url=$(urlencode "$GREENHOUSE_BUILD_URL") - pr="$GREENHOUSE_PULL_REQUEST" - commit="$GREENHOUSE_COMMIT" - search_in="$search_in $GREENHOUSE_EXPORT_DIR" - -elif [ "$GITLAB_CI" != "" ]; -then - say "$e==>$x GitLab CI detected." - # http://doc.gitlab.com/ce/ci/variables/README.html - service="gitlab" - branch="${CI_BUILD_REF_NAME:-$CI_COMMIT_REF_NAME}" - build="${CI_BUILD_ID:-$CI_JOB_ID}" - remote_addr="${CI_BUILD_REPO:-$CI_REPOSITORY_URL}" - commit="${CI_BUILD_REF:-$CI_COMMIT_SHA}" - slug="${CI_PROJECT_PATH}" - -elif [ "$GITHUB_ACTIONS" != "" ]; -then - say "$e==>$x GitHub Actions detected." - say " Env vars used:" - say " -> GITHUB_ACTIONS: ${GITHUB_ACTIONS}" - say " -> GITHUB_HEAD_REF: ${GITHUB_HEAD_REF}" - say " -> GITHUB_REF: ${GITHUB_REF}" - say " -> GITHUB_REPOSITORY: ${GITHUB_REPOSITORY}" - say " -> GITHUB_RUN_ID: ${GITHUB_RUN_ID}" - say " -> GITHUB_SHA: ${GITHUB_SHA}" - say " -> GITHUB_WORKFLOW: ${GITHUB_WORKFLOW}" - - # https://github.com/features/actions - service="github-actions" - - # https://help.github.com/en/articles/virtual-environments-for-github-actions#environment-variables - branch="${GITHUB_REF#refs/heads/}" - if [ "$GITHUB_HEAD_REF" != "" ]; - then - # PR refs are in the format: refs/pull/7/merge - if [[ "$GITHUB_REF" =~ ^refs\/pull\/[0-9]+\/merge$ ]]; - then - pr="${GITHUB_REF#refs/pull/}" - pr="${pr%/merge}" - fi - branch="${GITHUB_HEAD_REF}" - fi - commit="${GITHUB_SHA}" - slug="${GITHUB_REPOSITORY}" - build="${GITHUB_RUN_ID}" - build_url=$(urlencode "${GITHUB_SERVER_URL:-https://github.com}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}") - job="$(urlencode "${GITHUB_WORKFLOW}")" - - # actions/checkout runs in detached HEAD - mc= - if [ -n "$pr" ] && [ "$pr" != false ] && [ "$commit_o" == "" ]; - then - mc=$(git show --no-patch --format="%P" 2>/dev/null || echo "") - - if [[ "$mc" =~ ^[a-z0-9]{40}[[:space:]][a-z0-9]{40}$ ]]; - then - mc=$(echo "$mc" | cut -d' ' -f2) - say " Fixing merge commit SHA $commit -> $mc" - commit=$mc - elif [[ "$mc" = "" ]]; - then - say "$r-> Issue detecting commit SHA. Please run actions/checkout with fetch-depth > 1 or set to 0$x" - fi - fi - -elif [ "$SYSTEM_TEAMFOUNDATIONSERVERURI" != "" ]; -then - say "$e==>$x Azure Pipelines detected." - # https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=vsts - # https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&viewFallbackFrom=vsts&tabs=yaml - service="azure_pipelines" - commit="$BUILD_SOURCEVERSION" - build="$BUILD_BUILDNUMBER" - if [ -z "$SYSTEM_PULLREQUEST_PULLREQUESTNUMBER" ]; - then - pr="$SYSTEM_PULLREQUEST_PULLREQUESTID" - else - pr="$SYSTEM_PULLREQUEST_PULLREQUESTNUMBER" - fi - project="${SYSTEM_TEAMPROJECT}" - server_uri="${SYSTEM_TEAMFOUNDATIONSERVERURI}" - job="${BUILD_BUILDID}" - branch="${BUILD_SOURCEBRANCH#"refs/heads/"}" - build_url=$(urlencode "${SYSTEM_TEAMFOUNDATIONSERVERURI}${SYSTEM_TEAMPROJECT}/_build/results?buildId=${BUILD_BUILDID}") - - # azure/pipelines runs in detached HEAD - mc= - if [ -n "$pr" ] && [ "$pr" != false ]; - then - mc=$(git show --no-patch --format="%P" 2>/dev/null || echo "") - - if [[ "$mc" =~ ^[a-z0-9]{40}[[:space:]][a-z0-9]{40}$ ]]; - then - mc=$(echo "$mc" | cut -d' ' -f2) - say " Fixing merge commit SHA $commit -> $mc" - commit=$mc - fi - fi - -elif [ "$CI" = "true" ] && [ "$BITBUCKET_BUILD_NUMBER" != "" ]; -then - say "$e==>$x Bitbucket detected." - # https://confluence.atlassian.com/bitbucket/variables-in-pipelines-794502608.html - service="bitbucket" - branch="$BITBUCKET_BRANCH" - build="$BITBUCKET_BUILD_NUMBER" - slug="$BITBUCKET_REPO_OWNER/$BITBUCKET_REPO_SLUG" - job="$BITBUCKET_BUILD_NUMBER" - pr="$BITBUCKET_PR_ID" - commit="$BITBUCKET_COMMIT" - # See https://jira.atlassian.com/browse/BCLOUD-19393 - if [ "${#commit}" = 12 ]; - then - commit=$(git rev-parse "$BITBUCKET_COMMIT") - fi - -elif [ "$CI" = "true" ] && [ "$BUDDY" = "true" ]; -then - say "$e==>$x Buddy CI detected." - # https://buddy.works/docs/pipelines/environment-variables - service="buddy" - branch="$BUDDY_EXECUTION_BRANCH" - build="$BUDDY_EXECUTION_ID" - build_url=$(urlencode "$BUDDY_EXECUTION_URL") - commit="$BUDDY_EXECUTION_REVISION" - pr="$BUDDY_EXECUTION_PULL_REQUEST_NO" - tag="$BUDDY_EXECUTION_TAG" - slug="$BUDDY_REPO_SLUG" - -elif [ "$CIRRUS_CI" != "" ]; -then - say "$e==>$x Cirrus CI detected." - # https://cirrus-ci.org/guide/writing-tasks/#environment-variables - service="cirrus-ci" - slug="$CIRRUS_REPO_FULL_NAME" - branch="$CIRRUS_BRANCH" - pr="$CIRRUS_PR" - commit="$CIRRUS_CHANGE_IN_REPO" - build="$CIRRUS_BUILD_ID" - build_url=$(urlencode "https://cirrus-ci.com/task/$CIRRUS_TASK_ID") - job="$CIRRUS_TASK_NAME" - -elif [ "$DOCKER_REPO" != "" ]; -then - say "$e==>$x Docker detected." - # https://docs.docker.com/docker-cloud/builds/advanced/ - service="docker" - branch="$SOURCE_BRANCH" - commit="$SOURCE_COMMIT" - slug="$DOCKER_REPO" - tag="$CACHE_TAG" - env="$env,IMAGE_NAME" - -else - say "${r}x>${x} No CI provider detected." - say " Testing inside Docker? ${b}http://docs.codecov.io/docs/testing-with-docker${x}" - say " Testing with Tox? ${b}https://docs.codecov.io/docs/python#section-testing-with-tox${x}" - -fi - -say " ${e}current dir: ${x} $PWD" -say " ${e}project root:${x} $git_root" - -# find branch, commit, repo from git command -if [ "$GIT_BRANCH" != "" ]; -then - branch="$GIT_BRANCH" - -elif [ "$branch" = "" ]; -then - branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || hg branch 2>/dev/null || echo "") - if [ "$branch" = "HEAD" ]; - then - branch="" - fi -fi - -if [ "$commit_o" = "" ]; -then - if [ "$GIT_COMMIT" != "" ]; - then - commit="$GIT_COMMIT" - elif [ "$commit" = "" ]; - then - commit=$(git log -1 --format="%H" 2>/dev/null || hg id -i --debug 2>/dev/null | tr -d '+' || echo "") - fi -else - commit="$commit_o" -fi - -if [ "$CODECOV_TOKEN" != "" ] && [ "$token" = "" ]; -then - say "${e}-->${x} token set from env" - token="$CODECOV_TOKEN" -fi - -if [ "$CODECOV_URL" != "" ] && [ "$url_o" = "" ]; -then - say "${e}-->${x} url set from env" - url_o=$(echo "$CODECOV_URL" | sed -e 's/\/$//') -fi - -if [ "$CODECOV_SLUG" != "" ]; -then - say "${e}-->${x} slug set from env" - slug_o="$CODECOV_SLUG" - -elif [ "$slug" = "" ]; -then - if [ "$remote_addr" = "" ]; - then - remote_addr=$(git config --get remote.origin.url || hg paths default || echo '') - fi - if [ "$remote_addr" != "" ]; - then - if echo "$remote_addr" | grep -q "//"; then - # https - slug=$(echo "$remote_addr" | cut -d / -f 4,5 | sed -e 's/\.git$//') - else - # ssh - slug=$(echo "$remote_addr" | cut -d : -f 2 | sed -e 's/\.git$//') - fi - fi - if [ "$slug" = "/" ]; - then - slug="" - fi -fi - -yaml=$(cd "$git_root" && \ - git ls-files "*codecov.yml" "*codecov.yaml" 2>/dev/null \ - || hg locate "*codecov.yml" "*codecov.yaml" 2>/dev/null \ - || cd "$proj_root" && find . -maxdepth 1 -type f -name '*codecov.y*ml' 2>/dev/null \ - || echo '') -yaml=$(echo "$yaml" | head -1) - -if [ "$yaml" != "" ]; -then - say " ${e}Yaml found at:${x} $yaml" - if [[ "$yaml" != /* ]]; then - # relative path for yaml file given, assume relative to the repo root - yaml="$git_root/$yaml" - fi - config=$(parse_yaml "$yaml" || echo '') - - # TODO validate the yaml here - - if [ "$(echo "$config" | grep 'codecov_token="')" != "" ] && [ "$token" = "" ]; - then - say "${e}-->${x} token set from yaml" - token="$(echo "$config" | grep 'codecov_token="' | sed -e 's/codecov_token="//' | sed -e 's/"\.*//')" - fi - - if [ "$(echo "$config" | grep 'codecov_url="')" != "" ] && [ "$url_o" = "" ]; - then - say "${e}-->${x} url set from yaml" - url_o="$(echo "$config" | grep 'codecov_url="' | sed -e 's/codecov_url="//' | sed -e 's/"\.*//')" - fi - - if [ "$(echo "$config" | grep 'codecov_slug="')" != "" ] && [ "$slug_o" = "" ]; - then - say "${e}-->${x} slug set from yaml" - slug_o="$(echo "$config" | grep 'codecov_slug="' | sed -e 's/codecov_slug="//' | sed -e 's/"\.*//')" - fi -else - say " ${g}Yaml not found, that's ok! Learn more at${x} ${b}http://docs.codecov.io/docs/codecov-yaml${x}" -fi - -if [ "$branch_o" != "" ]; -then - branch=$(urlencode "$branch_o") -else - branch=$(urlencode "$branch") -fi - -if [ "$slug_o" = "" ]; -then - urlencoded_slug=$(urlencode "$slug") -else - urlencoded_slug=$(urlencode "$slug_o") -fi - -query="branch=$branch\ - &commit=$commit\ - &build=$([ "$build_o" = "" ] && echo "$build" || echo "$build_o")\ - &build_url=$build_url\ - &name=$(urlencode "$name")\ - &tag=$([ "$tag_o" = "" ] && echo "$tag" || echo "$tag_o")\ - &slug=$urlencoded_slug\ - &service=$service\ - &flags=$flags\ - &pr=$([ "$pr_o" = "" ] && echo "${pr##\#}" || echo "${pr_o##\#}")\ - &job=$job\ - &cmd_args=$(IFS=,; echo "${codecov_flags[*]}")" - -if [ -n "$project" ] && [ -n "$server_uri" ]; -then - query=$(echo "$query&project=$project&server_uri=$server_uri" | tr -d ' ') -fi - -if [ "$parent" != "" ]; -then - query=$(echo "parent=$parent&$query" | tr -d ' ') -fi - -if [ "$ft_search" = "1" ]; -then - # detect bower comoponents location - bower_components="bower_components" - bower_rc=$(cd "$git_root" && cat .bowerrc 2>/dev/null || echo "") - if [ "$bower_rc" != "" ]; - then - bower_components=$(echo "$bower_rc" | tr -d '\n' | grep '"directory"' | cut -d'"' -f4 | sed -e 's/\/$//') - if [ "$bower_components" = "" ]; - then - bower_components="bower_components" - fi - fi - - # Swift Coverage - if [ "$ft_xcodellvm" = "1" ] && [ -d "$ddp" ]; - then - say "${e}==>${x} Processing Xcode reports via llvm-cov" - say " DerivedData folder: $ddp" - profdata_files=$(find "$ddp" -name '*.profdata' 2>/dev/null || echo '') - if [ "$profdata_files" != "" ]; - then - # xcode via profdata - if [ "$xp" = "" ]; - then - # xp=$(xcodebuild -showBuildSettings 2>/dev/null | grep -i "^\s*PRODUCT_NAME" | sed -e 's/.*= \(.*\)/\1/') - # say " ${e}->${x} Speed up Xcode processing by adding ${e}-J '$xp'${x}" - say " ${g}hint${x} Speed up Swift processing by using use ${g}-J 'AppName'${x} (regexp accepted)" - say " ${g}hint${x} This will remove Pods/ from your report. Also ${b}https://docs.codecov.io/docs/ignoring-paths${x}" - fi - while read -r profdata; - do - if [ "$profdata" != "" ]; - then - swiftcov "$profdata" "$xp" - fi - done <<< "$profdata_files" - else - say " ${e}->${x} No Swift coverage found" - fi - - # Obj-C Gcov Coverage - if [ "$ft_gcov" = "1" ]; - then - say " ${e}->${x} Running $gcov_exe for Obj-C" - if [ "$ft_gcovout" = "0" ]; - then - # suppress gcov output - bash -c "find $ddp -type f -name '*.gcda' $gcov_include $gcov_ignore -exec $gcov_exe -p $gcov_arg {} +" >/dev/null 2>&1 || true - else - bash -c "find $ddp -type f -name '*.gcda' $gcov_include $gcov_ignore -exec $gcov_exe -p $gcov_arg {} +" || true - fi - fi - fi - - if [ "$ft_xcodeplist" = "1" ] && [ -d "$ddp" ]; - then - say "${e}==>${x} Processing Xcode plists" - plists_files=$(find "$ddp" -name '*.xccoverage' 2>/dev/null || echo '') - if [ "$plists_files" != "" ]; - then - while read -r plist; - do - if [ "$plist" != "" ]; - then - say " ${g}Found${x} plist file at $plist" - plutil -convert xml1 -o "$(basename "$plist").plist" -- "$plist" - fi - done <<< "$plists_files" - fi - fi - - # Gcov Coverage - if [ "$ft_gcov" = "1" ]; - then - say "${e}==>${x} Running $gcov_exe in $proj_root ${e}(disable via -X gcov)${x}" - if [ "$ft_gcovout" = "0" ]; - then - # suppress gcov output - bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -exec $gcov_exe -pb $gcov_arg {} +" >/dev/null 2>&1 || true - else - bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -exec $gcov_exe -pb $gcov_arg {} +" || true - fi - else - say "${e}==>${x} gcov disabled" - fi - - # Python Coverage - if [ "$ft_coveragepy" = "1" ]; - then - if [ ! -f coverage.xml ]; - then - if command -v coverage >/dev/null 2>&1; - then - say "${e}==>${x} Python coveragepy exists ${e}disable via -X coveragepy${x}" - - dotcoverage=$(find "$git_root" -name '.coverage' -or -name '.coverage.*' | head -1 || echo '') - if [ "$dotcoverage" != "" ]; - then - cd "$(dirname "$dotcoverage")" - if [ ! -f .coverage ]; - then - say " ${e}->${x} Running coverage combine" - coverage combine -a - fi - say " ${e}->${x} Running coverage xml" - if [ "$(coverage xml -i)" != "No data to report." ]; - then - files="$files -$PWD/coverage.xml" - else - say " ${r}No data to report.${x}" - fi - cd "$proj_root" - else - say " ${r}No .coverage file found.${x}" - fi - else - say "${e}==>${x} Python coveragepy not found" - fi - fi - else - say "${e}==>${x} Python coveragepy disabled" - fi - - if [ "$search_in_o" != "" ]; - then - # location override - search_in="$search_in_o" - fi - - say "$e==>$x Searching for coverage reports in:" - for _path in $search_in - do - say " ${g}+${x} $_path" - done - - patterns="find $search_in \( \ - -name vendor \ - -or -name '$bower_components' \ - -or -name '.egg-info*' \ - -or -name 'conftest_*.c.gcov' \ - -or -name .env \ - -or -name .envs \ - -or -name .git \ - -or -name .hg \ - -or -name .tox \ - -or -name .venv \ - -or -name .venvs \ - -or -name .virtualenv \ - -or -name .virtualenvs \ - -or -name .yarn-cache \ - -or -name __pycache__ \ - -or -name env \ - -or -name envs \ - -or -name htmlcov \ - -or -name js/generated/coverage \ - -or -name node_modules \ - -or -name venv \ - -or -name venvs \ - -or -name virtualenv \ - -or -name virtualenvs \ - \) -prune -or \ - -type f \( -name '*coverage*.*' \ - -or -name '*.clover' \ - -or -name '*.codecov.*' \ - -or -name '*.gcov' \ - -or -name '*.lcov' \ - -or -name '*.lst' \ - -or -name 'clover.xml' \ - -or -name 'cobertura.xml' \ - -or -name 'codecov.*' \ - -or -name 'cover.out' \ - -or -name 'codecov-result.json' \ - -or -name 'coverage-final.json' \ - -or -name 'excoveralls.json' \ - -or -name 'gcov.info' \ - -or -name 'jacoco*.xml' \ - -or -name '*Jacoco*.xml' \ - -or -name 'lcov.dat' \ - -or -name 'lcov.info' \ - -or -name 'luacov.report.out' \ - -or -name 'naxsi.info' \ - -or -name 'nosetests.xml' \ - -or -name 'report.xml' \ - $include_cov \) \ - $exclude_cov \ - -not -name '*.am' \ - -not -name '*.bash' \ - -not -name '*.bat' \ - -not -name '*.bw' \ - -not -name '*.cfg' \ - -not -name '*.class' \ - -not -name '*.cmake' \ - -not -name '*.cmake' \ - -not -name '*.conf' \ - -not -name '*.coverage' \ - -not -name '*.cp' \ - -not -name '*.cpp' \ - -not -name '*.crt' \ - -not -name '*.css' \ - -not -name '*.csv' \ - -not -name '*.csv' \ - -not -name '*.data' \ - -not -name '*.db' \ - -not -name '*.dox' \ - -not -name '*.ec' \ - -not -name '*.ec' \ - -not -name '*.egg' \ - -not -name '*.el' \ - -not -name '*.env' \ - -not -name '*.erb' \ - -not -name '*.exe' \ - -not -name '*.ftl' \ - -not -name '*.gif' \ - -not -name '*.gradle' \ - -not -name '*.gz' \ - -not -name '*.h' \ - -not -name '*.html' \ - -not -name '*.in' \ - -not -name '*.jade' \ - -not -name '*.jar*' \ - -not -name '*.jpeg' \ - -not -name '*.jpg' \ - -not -name '*.js' \ - -not -name '*.less' \ - -not -name '*.log' \ - -not -name '*.m4' \ - -not -name '*.mak*' \ - -not -name '*.md' \ - -not -name '*.o' \ - -not -name '*.p12' \ - -not -name '*.pem' \ - -not -name '*.png' \ - -not -name '*.pom*' \ - -not -name '*.profdata' \ - -not -name '*.proto' \ - -not -name '*.ps1' \ - -not -name '*.pth' \ - -not -name '*.py' \ - -not -name '*.pyc' \ - -not -name '*.pyo' \ - -not -name '*.rb' \ - -not -name '*.rsp' \ - -not -name '*.rst' \ - -not -name '*.ru' \ - -not -name '*.sbt' \ - -not -name '*.scss' \ - -not -name '*.scss' \ - -not -name '*.serialized' \ - -not -name '*.sh' \ - -not -name '*.snapshot' \ - -not -name '*.sql' \ - -not -name '*.svg' \ - -not -name '*.tar.tz' \ - -not -name '*.template' \ - -not -name '*.whl' \ - -not -name '*.xcconfig' \ - -not -name '*.xcoverage.*' \ - -not -name '*/classycle/report.xml' \ - -not -name '*codecov.yml' \ - -not -name '*~' \ - -not -name '.*coveragerc' \ - -not -name '.coverage*' \ - -not -name 'coverage-summary.json' \ - -not -name 'createdFiles.lst' \ - -not -name 'fullLocaleNames.lst' \ - -not -name 'include.lst' \ - -not -name 'inputFiles.lst' \ - -not -name 'phpunit-code-coverage.xml' \ - -not -name 'phpunit-coverage.xml' \ - -not -name 'remapInstanbul.coverage*.json' \ - -not -name 'scoverage.measurements.*' \ - -not -name 'test_*_coverage.txt' \ - -not -name 'testrunner-coverage*' \ - -print 2>/dev/null" - files=$(eval "$patterns" || echo '') - -elif [ "$include_cov" != "" ]; -then - files=$(eval "find $search_in -type f \( ${include_cov:5} \)$exclude_cov 2>/dev/null" || echo '') -elif [ "$direct_file_upload" != "" ]; -then - files=$direct_file_upload -fi - -num_of_files=$(echo "$files" | wc -l | tr -d ' ') -if [ "$num_of_files" != '' ] && [ "$files" != '' ]; -then - say " ${e}->${x} Found $num_of_files reports" -fi - -# no files found -if [ "$files" = "" ]; -then - say "${r}-->${x} No coverage report found." - say " Please visit ${b}http://docs.codecov.io/docs/supported-languages${x}" - exit ${exit_with}; -fi - -if [ "$ft_network" == "1" ]; -then - say "${e}==>${x} Detecting git/mercurial file structure" - network=$(cd "$git_root" && git ls-files $git_ls_files_recurse_submodules_o 2>/dev/null || hg locate 2>/dev/null || echo "") - if [ "$network" = "" ]; - then - network=$(find "$git_root" \( \ - -name virtualenv \ - -name .virtualenv \ - -name virtualenvs \ - -name .virtualenvs \ - -name '*.png' \ - -name '*.gif' \ - -name '*.jpg' \ - -name '*.jpeg' \ - -name '*.md' \ - -name .env \ - -name .envs \ - -name env \ - -name envs \ - -name .venv \ - -name .venvs \ - -name venv \ - -name venvs \ - -name .git \ - -name .egg-info \ - -name shunit2-2.1.6 \ - -name vendor \ - -name __pycache__ \ - -name node_modules \ - -path "*/$bower_components/*" \ - -path '*/target/delombok/*' \ - -path '*/build/lib/*' \ - -path '*/js/generated/coverage/*' \ - \) -prune -or \ - -type f -print 2>/dev/null || echo '') - fi - - if [ "$network_filter_o" != "" ]; - then - network=$(echo "$network" | grep -e "$network_filter_o/*") - fi - if [ "$prefix_o" != "" ]; - then - network=$(echo "$network" | awk "{print \"$prefix_o/\"\$0}") - fi -fi - -upload_file=$(mktemp /tmp/codecov.XXXXXX) -adjustments_file=$(mktemp /tmp/codecov.adjustments.XXXXXX) - -cleanup() { - rm -f "$upload_file" "$adjustments_file" "$upload_file.gz" -} - -trap cleanup INT ABRT TERM - - -if [ "$env" != "" ]; -then - inc_env="" - say "${e}==>${x} Appending build variables" - for varname in $(echo "$env" | tr ',' ' ') - do - if [ "$varname" != "" ]; - then - say " ${g}+${x} $varname" - inc_env="${inc_env}${varname}=$(eval echo "\$${varname}") -" - fi - done - echo "$inc_env<<<<<< ENV" >> "$upload_file" -fi - -# Append git file list -# write discovered yaml location -if [ "$direct_file_upload" = "" ]; -then - echo "$yaml" >> "$upload_file" -fi - -if [ "$ft_network" == "1" ]; -then - i="woff|eot|otf" # fonts - i="$i|gif|png|jpg|jpeg|psd" # images - i="$i|ptt|pptx|numbers|pages|md|txt|xlsx|docx|doc|pdf|csv" # docs - i="$i|.gitignore" # supporting docs - - if [ "$ft_html" != "1" ]; - then - i="$i|html" - fi - - if [ "$ft_yaml" != "1" ]; - then - i="$i|yml|yaml" - fi - - echo "$network" | grep -vwE "($i)$" >> "$upload_file" -fi -echo "<<<<<< network" >> "$upload_file" - -if [ "$direct_file_upload" = "" ]; -then - fr=0 - say "${e}==>${x} Reading reports" - while IFS='' read -r file; - do - # read the coverage file - if [ "$(echo "$file" | tr -d ' ')" != '' ]; - then - if [ -f "$file" ]; - then - report_len=$(wc -c < "$file") - if [ "$report_len" -ne 0 ]; - then - say " ${g}+${x} $file ${e}bytes=$(echo "$report_len" | tr -d ' ')${x}" - # append to to upload - _filename=$(basename "$file") - if [ "${_filename##*.}" = 'gcov' ]; - then - { - echo "# path=$(echo "$file.reduced" | sed "s|^$git_root/||")"; - # get file name - head -1 "$file"; - } >> "$upload_file" - # 1. remove source code - # 2. remove ending bracket lines - # 3. remove whitespace - # 4. remove contextual lines - # 5. remove function names - awk -F': *' '{print $1":"$2":"}' "$file" \ - | sed '\/: *} *$/d' \ - | sed 's/^ *//' \ - | sed '/^-/d' \ - | sed 's/^function.*/func/' >> "$upload_file" - else - { - echo "# path=${file//^$git_root/||}"; - cat "$file"; - } >> "$upload_file" - fi - echo "<<<<<< EOF" >> "$upload_file" - fr=1 - if [ "$clean" = "1" ]; - then - rm "$file" - fi - else - say " ${r}-${x} Skipping empty file $file" - fi - else - say " ${r}-${x} file not found at $file" - fi - fi - done <<< "$(echo -e "$files")" - - if [ "$fr" = "0" ]; - then - say "${r}-->${x} No coverage data found." - say " Please visit ${b}http://docs.codecov.io/docs/supported-languages${x}" - say " search for your projects language to learn how to collect reports." - exit ${exit_with}; - fi -else - cp "$direct_file_upload" "$upload_file" - if [ "$clean" = "1" ]; - then - rm "$direct_file_upload" - fi -fi - -if [ "$ft_fix" = "1" ]; -then - say "${e}==>${x} Appending adjustments" - say " ${b}https://docs.codecov.io/docs/fixing-reports${x}" - - empty_line='^[[:space:]]*$' - # // - syntax_comment='^[[:space:]]*//.*' - # /* or */ - syntax_comment_block='^[[:space:]]*(\/\*|\*\/)[[:space:]]*$' - # { or } - syntax_bracket='^[[:space:]]*[\{\}][[:space:]]*(//.*)?$' - # [ or ] - syntax_list='^[[:space:]]*[][][[:space:]]*(//.*)?$' - # func ... { - syntax_go_func='^[[:space:]]*func[[:space:]]*[\{][[:space:]]*$' - - # shellcheck disable=SC2089 - skip_dirs="-not -path '*/$bower_components/*' \ - -not -path '*/node_modules/*'" - - cut_and_join() { - awk 'BEGIN { FS=":" } - $3 ~ /\/\*/ || $3 ~ /\*\// { print $0 ; next } - $1!=key { if (key!="") print out ; key=$1 ; out=$1":"$2 ; next } - { out=out","$2 } - END { print out }' 2>/dev/null - } - - if echo "$network" | grep -m1 '.kt$' 1>/dev/null; - then - # skip brackets and comments - cd "$git_root" && \ - find . -type f \ - -name '*.kt' \ - -exec \ - grep -nIHE -e "$syntax_bracket" \ - -e "$syntax_comment_block" {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - - # last line in file - cd "$git_root" && \ - find . -type f \ - -name '*.kt' -exec \ - wc -l {} \; \ - | while read -r l; do echo "EOF: $l"; done \ - 2>/dev/null \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '.go$' 1>/dev/null; - then - # skip empty lines, comments, and brackets - cd "$git_root" && \ - find . -type f \ - -not -path '*/vendor/*' \ - -not -path '*/caches/*' \ - -name '*.go' \ - -exec \ - grep -nIHE \ - -e "$empty_line" \ - -e "$syntax_comment" \ - -e "$syntax_comment_block" \ - -e "$syntax_bracket" \ - -e "$syntax_go_func" \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '.dart$' 1>/dev/null; - then - # skip brackets - cd "$git_root" && \ - find . -type f \ - -name '*.dart' \ - -exec \ - grep -nIHE \ - -e "$syntax_bracket" \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '.php$' 1>/dev/null; - then - # skip empty lines, comments, and brackets - cd "$git_root" && \ - find . -type f \ - -not -path "*/vendor/*" \ - -name '*.php' \ - -exec \ - grep -nIHE \ - -e "$syntax_list" \ - -e "$syntax_bracket" \ - -e '^[[:space:]]*\);[[:space:]]*(//.*)?$' \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '\(.c\.cpp\|.cxx\|.h\|.hpp\|.m\|.swift\|.vala\)$' 1>/dev/null; - then - # skip brackets - # shellcheck disable=SC2086,SC2090 - cd "$git_root" && \ - find . -type f \ - $skip_dirs \ - \( \ - -name '*.c' \ - -or -name '*.cpp' \ - -or -name '*.cxx' \ - -or -name '*.h' \ - -or -name '*.hpp' \ - -or -name '*.m' \ - -or -name '*.swift' \ - -or -name '*.vala' \ - \) -exec \ - grep -nIHE \ - -e "$empty_line" \ - -e "$syntax_bracket" \ - -e '// LCOV_EXCL' \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - - # skip brackets - # shellcheck disable=SC2086,SC2090 - cd "$git_root" && \ - find . -type f \ - $skip_dirs \ - \( \ - -name '*.c' \ - -or -name '*.cpp' \ - -or -name '*.cxx' \ - -or -name '*.h' \ - -or -name '*.hpp' \ - -or -name '*.m' \ - -or -name '*.swift' \ - -or -name '*.vala' \ - \) -exec \ - grep -nIH '// LCOV_EXCL' \ - {} \; \ - >> "$adjustments_file" \ - || echo '' - - fi - - found=$(< "$adjustments_file" tr -d ' ') - - if [ "$found" != "" ]; - then - say " ${g}+${x} Found adjustments" - { - echo "# path=fixes"; - cat "$adjustments_file"; - echo "<<<<<< EOF"; - } >> "$upload_file" - rm -rf "$adjustments_file" - else - say " ${e}->${x} No adjustments found" - fi -fi - -if [ "$url_o" != "" ]; -then - url="$url_o" -fi - -if [ "$dump" != "0" ]; -then - # trim whitespace from query - say " ${e}->${x} Dumping upload file (no upload)" - echo "$url/upload/v4?$(echo "package=$package-$VERSION&$query" | tr -d ' ')" - cat "$upload_file" -else - if [ "$save_to" != "" ]; - then - say "${e}==>${x} Copying upload file to ${save_to}" - mkdir -p "$(dirname "$save_to")" - cp "$upload_file" "$save_to" - fi - - say "${e}==>${x} Gzipping contents" - gzip -nf9 "$upload_file" - say " $(du -h "$upload_file.gz")" - - query=$(echo "${query}" | tr -d ' ') - say "${e}==>${x} Uploading reports" - say " ${e}url:${x} $url" - say " ${e}query:${x} $query" - - # Full query (to display on terminal output) - query=$(echo "package=$package-$VERSION&token=$token&$query" | tr -d ' ') - queryNoToken=$(echo "package=$package-$VERSION&token=&$query" | tr -d ' ') - - if [ "$ft_s3" = "1" ]; - then - say "${e}->${x} Pinging Codecov" - say "$url/upload/v4?$queryNoToken" - # shellcheck disable=SC2086,2090 - res=$(curl $curl_s -X POST $cacert \ - --retry 5 --retry-delay 2 --connect-timeout 2 \ - -H 'X-Reduced-Redundancy: false' \ - -H 'X-Content-Type: application/x-gzip' \ - -H 'Content-Length: 0' \ - -H "X-Upload-Token: ${token}" \ - --write-out "\n%{response_code}\n" \ - $curlargs \ - "$url/upload/v4?$query" || true) - # a good reply is "https://codecov.io" + "\n" + "https://storage.googleapis.com/codecov/..." - s3target=$(echo "$res" | sed -n 2p) - status=$(tail -n1 <<< "$res") - - if [ "$status" = "200" ] && [ "$s3target" != "" ]; - then - say "${e}->${x} Uploading to" - say "${s3target}" - - # shellcheck disable=SC2086 - s3=$(curl -fiX PUT \ - --data-binary @"$upload_file.gz" \ - -H 'Content-Type: application/x-gzip' \ - -H 'Content-Encoding: gzip' \ - $curlawsargs \ - "$s3target" || true) - - if [ "$s3" != "" ]; - then - say " ${g}->${x} Reports have been successfully queued for processing at ${b}$(echo "$res" | sed -n 1p)${x}" - exit 0 - else - say " ${r}X>${x} Failed to upload" - fi - elif [ "$status" = "400" ]; - then - # 400 Error - say "${r}${res}${x}" - exit ${exit_with} - else - say "${r}${res}${x}" - fi - fi - - say "${e}==>${x} Uploading to Codecov" - - # shellcheck disable=SC2086,2090 - res=$(curl -X POST $cacert \ - --data-binary @"$upload_file.gz" \ - --retry 5 --retry-delay 2 --connect-timeout 2 \ - -H 'Content-Type: text/plain' \ - -H 'Content-Encoding: gzip' \ - -H 'X-Content-Encoding: gzip' \ - -H "X-Upload-Token: ${token}" \ - -H 'Accept: text/plain' \ - $curlargs \ - "$url/upload/v2?$query&attempt=$i" || echo 'HTTP 500') - # {"message": "Coverage reports upload successfully", "uploaded": true, "queued": true, "id": "...", "url": "https://codecov.io/..."\} - uploaded=$(grep -o '\"uploaded\": [a-z]*' <<< "$res" | head -1 | cut -d' ' -f2) - if [ "$uploaded" = "true" ] - then - say " Reports have been successfully queued for processing at ${b}$(echo "$res" | head -2 | tail -1)${x}" - exit 0 - else - say " ${g}${res}${x}" - exit ${exit_with} - fi - - say " ${r}X> Failed to upload coverage reports${x}" -fi - -exit ${exit_with} diff --git a/tools/bin/go_core_tests b/tools/bin/go_core_tests index 694a51d1f82..c0b0f43aed4 100755 --- a/tools/bin/go_core_tests +++ b/tools/bin/go_core_tests @@ -32,7 +32,5 @@ if [[ $EXITCODE != 0 ]]; then echo "Encountered test failures." else echo "All tests passed!" - # uploading coverage.txt to CodeCov - $(dirname "$0")/codecov -f coverage.txt fi exit $EXITCODE From 0a37c0ed5346df509b545c88278c026cb2adf375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deividas=20Kar=C5=BEinauskas?= Date: Mon, 29 Apr 2024 08:32:38 +0300 Subject: [PATCH 34/34] CapabilityRegistry: add capability version (#12996) * Add capability response type and configuration contract * MUST NOT override existing capability version * MUST match configuration contract interface * Add wrappers * Include a tag to core changeset * Update ICapabilityConfiguration * Regen wrappers --- .changeset/curvy-weeks-cover.md | 5 ++ contracts/.changeset/funny-eagles-know.md | 5 ++ .../src/v0.8/keystone/CapabilityRegistry.sol | 58 +++++++++++++ .../interfaces/ICapabilityConfiguration.sol | 27 ++++++ .../src/v0.8/keystone/test/BaseTest.t.sol | 3 + ...CapabilityRegistry_AddCapabilityTest.t.sol | 82 +++++++++++++++++-- .../mocks/CapabilityConfigurationContract.sol | 13 +++ .../keystone_capability_registry.go | 10 ++- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 9 files changed, 195 insertions(+), 10 deletions(-) create mode 100644 .changeset/curvy-weeks-cover.md create mode 100644 contracts/.changeset/funny-eagles-know.md create mode 100644 contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol create mode 100644 contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol diff --git a/.changeset/curvy-weeks-cover.md b/.changeset/curvy-weeks-cover.md new file mode 100644 index 00000000000..0b19df8ad16 --- /dev/null +++ b/.changeset/curvy-weeks-cover.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#wip Keystone contract wrappers updated diff --git a/contracts/.changeset/funny-eagles-know.md b/contracts/.changeset/funny-eagles-know.md new file mode 100644 index 00000000000..46827824ad8 --- /dev/null +++ b/contracts/.changeset/funny-eagles-know.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +#wip addCapability udpates diff --git a/contracts/src/v0.8/keystone/CapabilityRegistry.sol b/contracts/src/v0.8/keystone/CapabilityRegistry.sol index faedd858bef..17f5a3dd73f 100644 --- a/contracts/src/v0.8/keystone/CapabilityRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilityRegistry.sol @@ -3,8 +3,14 @@ pragma solidity ^0.8.0; import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol"; import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; +import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {EnumerableSet} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; +import {ICapabilityConfiguration} from "./interfaces/ICapabilityConfiguration.sol"; contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { + // Add the library methods + using EnumerableSet for EnumerableSet.Bytes32Set; + struct NodeOperator { /// @notice The address of the admin that can manage a node /// operator @@ -13,6 +19,16 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { string name; } + // CapabilityResponseType indicates whether remote response requires + // aggregation or is an already aggregated report. There are multiple + // possible ways to aggregate. + enum CapabilityResponseType { + // No additional aggregation is needed on the remote response. + REPORT, + // A number of identical observations need to be aggregated. + OBSERVATION_IDENTICAL + } + struct Capability { // Capability type, e.g. "data-streams-reports" // bytes32(string); validation regex: ^[a-z0-9_\-:]{1,32}$ @@ -21,12 +37,39 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { // Semver, e.g., "1.2.3" // bytes32(string); must be valid Semver + max 32 characters. bytes32 version; + // responseType indicates whether remote response requires + // aggregation or is an OCR report. There are multiple possible + // ways to aggregate. + CapabilityResponseType responseType; + // An address to the capability configuration contract. Having this defined + // on a capability enforces consistent configuration across DON instances + // serving the same capability. Configuration contract MUST implement + // CapabilityConfigurationContractInterface. + // + // The main use cases are: + // 1) Sharing capability configuration across DON instances + // 2) Inspect and modify on-chain configuration without off-chain + // capability code. + // + // It is not recommended to store configuration which requires knowledge of + // the DON membership. + address configurationContract; } /// @notice This error is thrown when trying to set a node operator's /// admin address to the zero address error InvalidNodeOperatorAdmin(); + /// @notice This error is thrown when trying add a capability that already + /// exists. + error CapabilityAlreadyExists(); + + /// @notice This error is thrown when trying to add a capability with a + /// configuration contract that does not implement the required interface. + /// @param proposedConfigurationContract The address of the proposed + /// configuration contract. + error InvalidCapabilityConfigurationContractInterface(address proposedConfigurationContract); + /// @notice This event is emitted when a new node operator is added /// @param nodeOperatorId The ID of the newly added node operator /// @param admin The address of the admin that can manage the node @@ -43,6 +86,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { event CapabilityAdded(bytes32 indexed capabilityId); mapping(bytes32 => Capability) private s_capabilities; + EnumerableSet.Bytes32Set private s_capabilityIds; /// @notice Mapping of node operators mapping(uint256 nodeOperatorId => NodeOperator) private s_nodeOperators; @@ -87,7 +131,21 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { function addCapability(Capability calldata capability) external onlyOwner { bytes32 capabilityId = getCapabilityID(capability.capabilityType, capability.version); + + if (s_capabilityIds.contains(capabilityId)) revert CapabilityAlreadyExists(); + + if (capability.configurationContract != address(0)) { + if ( + capability.configurationContract.code.length == 0 || + !IERC165(capability.configurationContract).supportsInterface( + ICapabilityConfiguration.getCapabilityConfiguration.selector + ) + ) revert InvalidCapabilityConfigurationContractInterface(capability.configurationContract); + } + + s_capabilityIds.add(capabilityId); s_capabilities[capabilityId] = capability; + emit CapabilityAdded(capabilityId); } diff --git a/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol b/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol new file mode 100644 index 00000000000..20447c9680a --- /dev/null +++ b/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/// @notice Interface for capability configuration contract. It MUST be +/// implemented for a contract to be used as a capability configuration. +/// The contract MAY store configuration that is shared across multiple +/// DON instances and capability versions. +/// @dev This interface does not guarantee the configuration contract's +/// correctness. It is the responsibility of the contract owner to ensure +/// that the configuration contract emits the CapabilityConfigurationSet +/// event when the configuration is set. +interface ICapabilityConfiguration { + /// @notice Emitted when a capability configuration is set. + event CapabilityConfigurationSet(); + + /// @notice Returns the capability configuration for a particular DON instance. + /// @dev donId is required to get DON-specific configuration. It avoids a + /// situation where configuration size grows too large. + /// @param donId The DON instance ID. These are stored in the CapabilityRegistry. + /// @return configuration DON's configuration for the capability. + function getCapabilityConfiguration(uint256 donId) external view returns (bytes memory configuration); + + // Solidity does not support generic returns types, so this cannot be part of + // the interface. However, the implementation contract MAY implement this + // function to enable configuration decoding on-chain. + // function decodeCapabilityConfiguration(bytes configuration) external returns (TypedCapabilityConfigStruct config) +} diff --git a/contracts/src/v0.8/keystone/test/BaseTest.t.sol b/contracts/src/v0.8/keystone/test/BaseTest.t.sol index 5c4b4c91809..4517a256b15 100644 --- a/contracts/src/v0.8/keystone/test/BaseTest.t.sol +++ b/contracts/src/v0.8/keystone/test/BaseTest.t.sol @@ -3,14 +3,17 @@ pragma solidity ^0.8.19; import {Test} from "forge-std/Test.sol"; import {Constants} from "./Constants.t.sol"; +import {CapabilityConfigurationContract} from "./mocks/CapabilityConfigurationContract.sol"; import {CapabilityRegistry} from "../CapabilityRegistry.sol"; contract BaseTest is Test, Constants { CapabilityRegistry internal s_capabilityRegistry; + CapabilityConfigurationContract internal s_capabilityConfigurationContract; function setUp() public virtual { vm.startPrank(ADMIN); s_capabilityRegistry = new CapabilityRegistry(); + s_capabilityConfigurationContract = new CapabilityConfigurationContract(); } function _getNodeOperators() internal view returns (CapabilityRegistry.NodeOperator[] memory) { diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol index 6fbdc43a2c7..d9e4b6b8383 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol @@ -2,16 +2,88 @@ pragma solidity ^0.8.19; import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilityConfigurationContract} from "./mocks/CapabilityConfigurationContract.sol"; + import {CapabilityRegistry} from "../CapabilityRegistry.sol"; contract CapabilityRegistry_AddCapabilityTest is BaseTest { - function test_AddCapability() public { - s_capabilityRegistry.addCapability(CapabilityRegistry.Capability("data-streams-reports", "1.0.0")); + CapabilityRegistry.Capability private basicCapability = + CapabilityRegistry.Capability({ + capabilityType: "data-streams-reports", + version: "1.0.0", + responseType: CapabilityRegistry.CapabilityResponseType.REPORT, + configurationContract: address(0) + }); + + CapabilityRegistry.Capability private capabilityWithConfigurationContract = + CapabilityRegistry.Capability({ + capabilityType: "read-ethereum-mainnet-gas-price", + version: "1.0.2", + responseType: CapabilityRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL, + configurationContract: address(s_capabilityConfigurationContract) + }); + + function test_RevertWhen_CalledByNonAdmin() public { + changePrank(STRANGER); + + vm.expectRevert("Only callable by owner"); + s_capabilityRegistry.addCapability(basicCapability); + } + + function test_RevertWhen_CapabilityExists() public { + // Successfully add the capability the first time + s_capabilityRegistry.addCapability(basicCapability); + + // Try to add the same capability again + vm.expectRevert(CapabilityRegistry.CapabilityAlreadyExists.selector); + s_capabilityRegistry.addCapability(basicCapability); + } + + function test_RevertWhen_ConfigurationContractNotDeployed() public { + address nonExistentContract = address(1); + capabilityWithConfigurationContract.configurationContract = nonExistentContract; + + vm.expectRevert( + abi.encodeWithSelector( + CapabilityRegistry.InvalidCapabilityConfigurationContractInterface.selector, + nonExistentContract + ) + ); + s_capabilityRegistry.addCapability(capabilityWithConfigurationContract); + } + + function test_RevertWhen_ConfigurationContractDoesNotMatchInterface() public { + CapabilityRegistry contractWithoutERC165 = new CapabilityRegistry(); + + vm.expectRevert(); + capabilityWithConfigurationContract.configurationContract = address(contractWithoutERC165); + s_capabilityRegistry.addCapability(capabilityWithConfigurationContract); + } + + function test_AddCapability_NoConfigurationContract() public { + s_capabilityRegistry.addCapability(basicCapability); bytes32 capabilityId = s_capabilityRegistry.getCapabilityID(bytes32("data-streams-reports"), bytes32("1.0.0")); - CapabilityRegistry.Capability memory capability = s_capabilityRegistry.getCapability(capabilityId); + CapabilityRegistry.Capability memory storedCapability = s_capabilityRegistry.getCapability(capabilityId); + + assertEq(storedCapability.capabilityType, basicCapability.capabilityType); + assertEq(storedCapability.version, basicCapability.version); + assertEq(uint256(storedCapability.responseType), uint256(basicCapability.responseType)); + assertEq(storedCapability.configurationContract, basicCapability.configurationContract); + } + + function test_AddCapability_WithConfiguration() public { + s_capabilityRegistry.addCapability(capabilityWithConfigurationContract); + + bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( + bytes32(capabilityWithConfigurationContract.capabilityType), + bytes32(capabilityWithConfigurationContract.version) + ); + CapabilityRegistry.Capability memory storedCapability = s_capabilityRegistry.getCapability(capabilityId); - assertEq(capability.capabilityType, "data-streams-reports"); - assertEq(capability.version, "1.0.0"); + assertEq(storedCapability.capabilityType, capabilityWithConfigurationContract.capabilityType); + assertEq(storedCapability.version, capabilityWithConfigurationContract.version); + assertEq(uint256(storedCapability.responseType), uint256(capabilityWithConfigurationContract.responseType)); + assertEq(storedCapability.configurationContract, capabilityWithConfigurationContract.configurationContract); } } diff --git a/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol b/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol new file mode 100644 index 00000000000..0c3d8e0597d --- /dev/null +++ b/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ICapabilityConfiguration} from "../../interfaces/ICapabilityConfiguration.sol"; +import {ERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165.sol"; + +contract CapabilityConfigurationContract is ICapabilityConfiguration, ERC165 { + mapping(uint256 => bytes) private s_donConfiguration; + + function getCapabilityConfiguration(uint256 donId) external view returns (bytes memory configuration) { + return s_donConfiguration[donId]; + } +} diff --git a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go index 47c65d5276b..7e3ca7027eb 100644 --- a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go +++ b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go @@ -31,8 +31,10 @@ var ( ) type CapabilityRegistryCapability struct { - CapabilityType [32]byte - Version [32]byte + CapabilityType [32]byte + Version [32]byte + ResponseType uint8 + ConfigurationContract common.Address } type CapabilityRegistryNodeOperator struct { @@ -41,8 +43,8 @@ type CapabilityRegistryNodeOperator struct { } var CapabilityRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b610ef1806101576000396000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80636e5f2869116100765780638da5cb5b1161005b5780638da5cb5b146101b65780639cb7c5f4146101de578063f2fde38b1461024557600080fd5b80636e5f28691461019b57806379ba5097146101ae57600080fd5b8063229111f5116100a7578063229111f514610120578063398f37731461016857806365c14dc71461017b57600080fd5b8063181f5a77146100c35780631cdf63431461010b575b600080fd5b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516101029190610957565b60405180910390f35b61011e6101193660046109bd565b610258565b005b61015a61012e3660046109ff565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b604051908152602001610102565b61011e6101763660046109bd565b61031b565b61018e610189366004610a21565b6104b4565b6040516101029190610a3a565b61011e6101a9366004610a7d565b61059a565b61011e610617565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610102565b61022a6101ec366004610a21565b604080518082019091526000808252602082015250600090815260026020908152604091829020825180840190935280548352600101549082015290565b60408051825181526020928301519281019290925201610102565b61011e610253366004610abe565b610719565b61026061072d565b60005b8181101561031657600083838381811061027f5761027f610ad9565b60209081029290920135600081815260039093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506102d060018301826108a5565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a15061030f81610b08565b9050610263565b505050565b61032361072d565b60005b8181101561031657600083838381811061034257610342610ad9565b90506020028101906103549190610b67565b61035d90610c4c565b805190915073ffffffffffffffffffffffffffffffffffffffff166103ae576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600454604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526003909252939020825181547fffffffffffffffffffffffff0000000000000000000000000000000000000000169216919091178155915190919060018201906104319082610db1565b5090505060046000815461044490610b08565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b9161049991859190610ecb565b60405180910390a25050806104ad90610b08565b9050610326565b6040805180820190915260008152606060208201526000828152600360209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff168352600181018054919284019161051190610d16565b80601f016020809104026020016040519081016040528092919081815260200182805461053d90610d16565b801561058a5780601f1061055f5761010080835404028352916020019161058a565b820191906000526020600020905b81548152906001019060200180831161056d57829003601f168201915b5050505050815250509050919050565b6105a261072d565b60408051823560208083018290528085013583850181905284518085038601815260609094018086528451948301949094206000818152600290935294822092835560019092019190915582917f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff069190a25050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461069d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61072161072d565b61072a816107b0565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610694565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361082f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610694565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b5080546108b190610d16565b6000825580601f106108c1575050565b601f01602090049060005260206000209081019061072a91905b808211156108ef57600081556001016108db565b5090565b6000815180845260005b81811015610919576020818501810151868301820152016108fd565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061096a60208301846108f3565b9392505050565b60008083601f84011261098357600080fd5b50813567ffffffffffffffff81111561099b57600080fd5b6020830191508360208260051b85010111156109b657600080fd5b9250929050565b600080602083850312156109d057600080fd5b823567ffffffffffffffff8111156109e757600080fd5b6109f385828601610971565b90969095509350505050565b60008060408385031215610a1257600080fd5b50508035926020909101359150565b600060208284031215610a3357600080fd5b5035919050565b6020815273ffffffffffffffffffffffffffffffffffffffff825116602082015260006020830151604080840152610a7560608401826108f3565b949350505050565b600060408284031215610a8f57600080fd5b50919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610ab957600080fd5b919050565b600060208284031215610ad057600080fd5b61096a82610a95565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610b60577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610b9b57600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610bf757610bf7610ba5565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610c4457610c44610ba5565b604052919050565b600060408236031215610c5e57600080fd5b610c66610bd4565b610c6f83610a95565b815260208084013567ffffffffffffffff80821115610c8d57600080fd5b9085019036601f830112610ca057600080fd5b813581811115610cb257610cb2610ba5565b610ce2847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610bfd565b91508082523684828501011115610cf857600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c90821680610d2a57607f821691505b602082108103610a8f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b601f82111561031657600081815260208120601f850160051c81016020861015610d8a5750805b601f850160051c820191505b81811015610da957828155600101610d96565b505050505050565b815167ffffffffffffffff811115610dcb57610dcb610ba5565b610ddf81610dd98454610d16565b84610d63565b602080601f831160018114610e325760008415610dfc5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610da9565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015610e7f57888601518255948401946001909101908401610e60565b5085821015610ebb57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b828152604060208201526000610a7560408301846108f356fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6112cb806101576000396000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c806365c14dc7116100765780638da5cb5b1161005b5780638da5cb5b1461018f5780639cb7c5f4146101b7578063f2fde38b146101d757600080fd5b806365c14dc71461016757806379ba50971461018757600080fd5b80631cdf6343116100a75780631cdf634314610120578063229111f514610133578063398f37731461015457600080fd5b8063117392ce146100c3578063181f5a77146100d8575b600080fd5b6100d66100d1366004610b88565b6101ea565b005b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516101179190610c04565b60405180910390f35b6100d661012e366004610c63565b610420565b610146610141366004610ca5565b6104e3565b604051908152602001610117565b6100d6610162366004610c63565b610512565b61017a610175366004610cc7565b6106ab565b6040516101179190610ce0565b6100d6610791565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610117565b6101ca6101c5366004610cc7565b61088e565b6040516101179190610d52565b6100d66101e5366004610df0565b610938565b6101f261094c565b6000610203823560208401356104e3565b90506102106003826109cf565b15610247576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006102596080840160608501610df0565b73ffffffffffffffffffffffffffffffffffffffff16146103c9576102846080830160608401610df0565b73ffffffffffffffffffffffffffffffffffffffff163b158061036457506102b26080830160608401610df0565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa15801561033e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103629190610e0d565b155b156103c9576103796080830160608401610df0565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024015b60405180910390fd5b6103d46003826109ea565b50600081815260026020526040902082906103ef8282610e2f565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b61042861094c565b60005b818110156104de57600083838381811061044757610447610eb1565b60209081029290920135600081815260059093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506104986001830182610b3a565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a1506104d781610ee0565b905061042b565b505050565b604080516020808201859052818301849052825180830384018152606090920190925280519101205b92915050565b61051a61094c565b60005b818110156104de57600083838381811061053957610539610eb1565b905060200281019061054b9190610f3f565b61055490611024565b805190915073ffffffffffffffffffffffffffffffffffffffff166105a5576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600654604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526005909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815591519091906001820190610628908261118b565b5090505060066000815461063b90610ee0565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b91610690918591906112a5565b60405180910390a25050806106a490610ee0565b905061051d565b6040805180820190915260008152606060208201526000828152600560209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610708906110f0565b80601f0160208091040260200160405190810160405280929190818152602001828054610734906110f0565b80156107815780601f1061075657610100808354040283529160200191610781565b820191906000526020600020905b81548152906001019060200180831161076457829003601f168201915b5050505050815250509050919050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610812576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016103c0565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff16908111156108f7576108f7610d23565b600181111561090857610908610d23565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b61094061094c565b610949816109f6565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016103c0565b565b600081815260018301602052604081205415155b9392505050565b60006109e38383610aeb565b3373ffffffffffffffffffffffffffffffffffffffff821603610a75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016103c0565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054610b325750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561050c565b50600061050c565b508054610b46906110f0565b6000825580601f10610b56575050565b601f01602090049060005260206000209081019061094991905b80821115610b845760008155600101610b70565b5090565b600060808284031215610b9a57600080fd5b50919050565b6000815180845260005b81811015610bc657602081850181015186830182015201610baa565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006109e36020830184610ba0565b60008083601f840112610c2957600080fd5b50813567ffffffffffffffff811115610c4157600080fd5b6020830191508360208260051b8501011115610c5c57600080fd5b9250929050565b60008060208385031215610c7657600080fd5b823567ffffffffffffffff811115610c8d57600080fd5b610c9985828601610c17565b90969095509350505050565b60008060408385031215610cb857600080fd5b50508035926020909101359150565b600060208284031215610cd957600080fd5b5035919050565b6020815273ffffffffffffffffffffffffffffffffffffffff825116602082015260006020830151604080840152610d1b6060840182610ba0565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b81518152602080830151908201526040820151608082019060028110610da1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8060408401525073ffffffffffffffffffffffffffffffffffffffff606084015116606083015292915050565b73ffffffffffffffffffffffffffffffffffffffff8116811461094957600080fd5b600060208284031215610e0257600080fd5b81356109e381610dce565b600060208284031215610e1f57600080fd5b815180151581146109e357600080fd5b813581556020820135600182015560028101604083013560028110610e5357600080fd5b81546060850135610e6381610dce565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff000000000000000000000000000000000000000000841617178455505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610f38577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610f7357600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610fcf57610fcf610f7d565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561101c5761101c610f7d565b604052919050565b60006040823603121561103657600080fd5b61103e610fac565b823561104981610dce565b815260208381013567ffffffffffffffff8082111561106757600080fd5b9085019036601f83011261107a57600080fd5b81358181111561108c5761108c610f7d565b6110bc847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610fd5565b915080825236848285010111156110d257600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c9082168061110457607f821691505b602082108103610b9a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b601f8211156104de57600081815260208120601f850160051c810160208610156111645750805b601f850160051c820191505b8181101561118357828155600101611170565b505050505050565b815167ffffffffffffffff8111156111a5576111a5610f7d565b6111b9816111b384546110f0565b8461113d565b602080601f83116001811461120c57600084156111d65750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611183565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156112595788860151825594840194600190910190840161123a565b508582101561129557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b828152604060208201526000610d1b6040830184610ba056fea164736f6c6343000813000a", } var CapabilityRegistryABI = CapabilityRegistryMetaData.ABI diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 62a75a8a644..66d26cead2d 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,4 @@ GETH_VERSION: 1.13.8 forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin b4c900aae9e022f01abbac7993d41f93912247613ac6270b0c4da4ef6f2016e3 -keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin 9eaa36e45c1b33c1fa72b7e25d6d1ca351413225611abb84ae053270b569cca4 +keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin d526b850decbf88dbe3dd66ed2160f1c311fb4ee6df0ac50c91f31521b361a52 ocr3_capability: ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin 9dcbdf55bd5729ba266148da3f17733eb592c871c2108ccca546618628fd9ad2